Merged in feature/VBV-641-vorschau-lernbegleitung (pull request #281)
Vorschau Lernbegleitung Approved-by: Christian Cueni
This commit is contained in:
commit
b9bdb745ce
|
|
@ -3,9 +3,11 @@ import { useTranslation } from "i18next-vue";
|
||||||
import { useRouteLookups } from "@/utils/route";
|
import { useRouteLookups } from "@/utils/route";
|
||||||
import { useCurrentCourseSession } from "@/composables";
|
import { useCurrentCourseSession } from "@/composables";
|
||||||
import { getCompetenceNaviUrl, getLearningPathUrl } from "@/utils/utils";
|
import { getCompetenceNaviUrl, getLearningPathUrl } from "@/utils/utils";
|
||||||
|
import { useCockpitStore } from "@/stores/cockpit";
|
||||||
|
|
||||||
const { inCompetenceProfile, inLearningPath } = useRouteLookups();
|
const { inCompetenceProfile, inLearningPath } = useRouteLookups();
|
||||||
const courseSession = useCurrentCourseSession();
|
const courseSession = useCurrentCourseSession();
|
||||||
|
const cockpit = useCockpitStore();
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -32,6 +34,7 @@ const { t } = useTranslation();
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<router-link
|
<router-link
|
||||||
|
v-if="cockpit.hasExpertCockpitType"
|
||||||
data-cy="preview-competence-profile-link"
|
data-cy="preview-competence-profile-link"
|
||||||
:to="getCompetenceNaviUrl(courseSession.course.slug)"
|
:to="getCompetenceNaviUrl(courseSession.course.slug)"
|
||||||
class="preview-nav-item"
|
class="preview-nav-item"
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,9 @@ const hasCockpitMenu = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasPreviewMenu = computed(() => {
|
const hasPreviewMenu = computed(() => {
|
||||||
return useCockpitStore().hasExpertCockpitType;
|
return (
|
||||||
|
useCockpitStore().hasExpertCockpitType || useCockpitStore().hasMentorCockpitType
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasAppointmentsMenu = computed(() => {
|
const hasAppointmentsMenu = computed(() => {
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,11 @@ const circleExperts = computed(() => {
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const learningContentReadonly = computed(() => {
|
||||||
|
const actions = courseSession.value.actions;
|
||||||
|
return props.readonly || !actions.includes("complete-learning-content");
|
||||||
|
});
|
||||||
|
|
||||||
const duration = computed(() => {
|
const duration = computed(() => {
|
||||||
// if (circleStore.circle) {
|
// if (circleStore.circle) {
|
||||||
// const minutes = sumBy(circleStore.circle.learningSequences, "minutes");
|
// const minutes = sumBy(circleStore.circle.learningSequences, "minutes");
|
||||||
|
|
@ -293,7 +298,7 @@ watch(
|
||||||
:course-slug="props.courseSlug"
|
:course-slug="props.courseSlug"
|
||||||
:circle="circle"
|
:circle="circle"
|
||||||
:learning-sequence="learningSequence"
|
:learning-sequence="learningSequence"
|
||||||
:readonly="props.readonly"
|
:readonly="learningContentReadonly"
|
||||||
></LearningSequence>
|
></LearningSequence>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
|
||||||
|
|
@ -448,6 +448,7 @@ export interface CourseSession {
|
||||||
start_date: string;
|
start_date: string;
|
||||||
end_date: string;
|
end_date: string;
|
||||||
due_dates: DueDate[];
|
due_dates: DueDate[];
|
||||||
|
actions: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CourseSessionUser = CourseSessionUserObjectsType;
|
export type CourseSessionUser = CourseSessionUserObjectsType;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ from vbv_lernwelt.course.models import (
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.duedate.models import DueDate
|
from vbv_lernwelt.duedate.models import DueDate
|
||||||
from vbv_lernwelt.duedate.serializers import DueDateSerializer
|
from vbv_lernwelt.duedate.serializers import DueDateSerializer
|
||||||
|
from vbv_lernwelt.iam.permissions import course_session_permissions
|
||||||
|
|
||||||
|
|
||||||
class CourseSerializer(serializers.ModelSerializer):
|
class CourseSerializer(serializers.ModelSerializer):
|
||||||
|
|
@ -54,15 +55,12 @@ class CourseSessionSerializer(serializers.ModelSerializer):
|
||||||
id = StringIDField()
|
id = StringIDField()
|
||||||
|
|
||||||
course = serializers.SerializerMethodField()
|
course = serializers.SerializerMethodField()
|
||||||
# course_url = serializers.SerializerMethodField()
|
|
||||||
due_dates = serializers.SerializerMethodField()
|
due_dates = serializers.SerializerMethodField()
|
||||||
|
actions = serializers.SerializerMethodField()
|
||||||
|
|
||||||
def get_course(self, obj):
|
def get_course(self, obj):
|
||||||
return CourseSerializer(obj.course).data
|
return CourseSerializer(obj.course).data
|
||||||
|
|
||||||
# def get_course_url(self, obj):
|
|
||||||
# return obj.course.get_course_url()
|
|
||||||
|
|
||||||
def get_due_dates(self, obj):
|
def get_due_dates(self, obj):
|
||||||
due_dates = DueDate.objects.filter(
|
due_dates = DueDate.objects.filter(
|
||||||
Q(start__isnull=False) | Q(end__isnull=False), course_session=obj
|
Q(start__isnull=False) | Q(end__isnull=False), course_session=obj
|
||||||
|
|
@ -80,7 +78,15 @@ class CourseSessionSerializer(serializers.ModelSerializer):
|
||||||
"start_date",
|
"start_date",
|
||||||
"end_date",
|
"end_date",
|
||||||
"due_dates",
|
"due_dates",
|
||||||
|
"actions",
|
||||||
]
|
]
|
||||||
|
read_only_fields = ["actions"]
|
||||||
|
|
||||||
|
def get_actions(self, obj):
|
||||||
|
user = self.context.get("user")
|
||||||
|
if user:
|
||||||
|
return course_session_permissions(user, obj.id)
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
class CircleDocumentSerializer(serializers.ModelSerializer):
|
class CircleDocumentSerializer(serializers.ModelSerializer):
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,10 @@ def get_course_sessions(request):
|
||||||
).distinct()
|
).distinct()
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
status=200, data=CourseSessionSerializer(all_to_serialize, many=True).data
|
status=200,
|
||||||
|
data=CourseSessionSerializer(
|
||||||
|
all_to_serialize, many=True, context={"user": request.user}
|
||||||
|
).data,
|
||||||
)
|
)
|
||||||
except PermissionDenied as e:
|
except PermissionDenied as e:
|
||||||
raise e
|
raise e
|
||||||
|
|
|
||||||
|
|
@ -207,3 +207,17 @@ def can_view_course_completions(
|
||||||
course_session_id=course_session_id,
|
course_session_id=course_session_id,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def course_session_permissions(user: User, course_session_id: int) -> list[str]:
|
||||||
|
return _action_list(
|
||||||
|
{
|
||||||
|
"complete-learning-content": is_course_session_member(
|
||||||
|
user, course_session_id
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _action_list(actions: dict[str, bool]):
|
||||||
|
return [action for action, allowed in actions.items() if allowed]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
from vbv_lernwelt.course.creators.test_utils import (
|
||||||
|
add_course_session_user,
|
||||||
|
create_course,
|
||||||
|
create_course_session,
|
||||||
|
create_user,
|
||||||
|
)
|
||||||
|
from vbv_lernwelt.course.models import CourseSessionUser
|
||||||
|
from vbv_lernwelt.iam.permissions import course_session_permissions
|
||||||
|
from vbv_lernwelt.learning_mentor.models import LearningMentor
|
||||||
|
|
||||||
|
|
||||||
|
class ActionTestCase(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.course, _ = create_course("Test Course")
|
||||||
|
self.course_session = create_course_session(
|
||||||
|
course=self.course, title="Test Session"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_course_session_permissions(self):
|
||||||
|
# GIVEN
|
||||||
|
lm = create_user("mentor")
|
||||||
|
LearningMentor.objects.create(
|
||||||
|
mentor=lm,
|
||||||
|
course=self.course,
|
||||||
|
)
|
||||||
|
|
||||||
|
participant = create_user("participant")
|
||||||
|
add_course_session_user(
|
||||||
|
self.course_session,
|
||||||
|
participant,
|
||||||
|
role=CourseSessionUser.Role.MEMBER,
|
||||||
|
)
|
||||||
|
|
||||||
|
# WHEN
|
||||||
|
mentor_actions = course_session_permissions(lm, self.course_session.id)
|
||||||
|
participant_actions = course_session_permissions(
|
||||||
|
participant, self.course_session.id
|
||||||
|
)
|
||||||
|
|
||||||
|
# THEN
|
||||||
|
self.assertEqual(len(mentor_actions), 0)
|
||||||
|
self.assertEqual(participant_actions, ["complete-learning-content"])
|
||||||
Loading…
Reference in New Issue