fix: prepare router / routing

This commit is contained in:
Livio Bieri 2024-03-13 10:36:55 +01:00
parent 16e0aba504
commit 050d0a6e72
9 changed files with 173 additions and 88 deletions

View File

@ -19,6 +19,7 @@ import {
getCockpitUrl, getCockpitUrl,
getCompetenceNaviUrl, getCompetenceNaviUrl,
getLearningMentorManagementUrl, getLearningMentorManagementUrl,
getLearningMentorUrl,
getLearningPathUrl, getLearningPathUrl,
getMediaCenterUrl, getMediaCenterUrl,
} from "@/utils/utils"; } from "@/utils/utils";
@ -109,7 +110,8 @@ const hasNotificationsMenu = computed(() => {
return userStore.loggedIn; return userStore.loggedIn;
}); });
const hasLearningMentor = computed(() => { // FIXME: Will be removed -> WIP
const hasDeprecatedLearningMentor = computed(() => {
if (!inCourse()) { if (!inCourse()) {
return false; return false;
} }
@ -125,9 +127,21 @@ const hasLearningMentor = computed(() => {
return false; return false;
} }
// FIXME: Use learning-mentor action instead of deprecated-mentor once we have moved everything from cockpit!
return courseSession.actions.includes("deprecated-mentor"); return courseSession.actions.includes("deprecated-mentor");
}); });
const hasLearningMentor = computed(() => {
if (!inCourse()) {
return false;
}
if (!courseSessionsStore.currentCourseSession) {
return false;
}
const courseSession = courseSessionsStore.currentCourseSession;
return courseSession.actions.includes("learning-mentor");
});
</script> </script>
<template> <template>
@ -262,7 +276,7 @@ const hasLearningMentor = computed(() => {
</router-link> </router-link>
<router-link <router-link
v-if="hasLearningMentor" v-if="hasDeprecatedLearningMentor"
data-cy="navigation-learning-mentor-link" data-cy="navigation-learning-mentor-link"
:to=" :to="
getLearningMentorManagementUrl( getLearningMentorManagementUrl(
@ -272,7 +286,20 @@ const hasLearningMentor = computed(() => {
class="nav-item" class="nav-item"
:class="{ 'nav-item--active': inLearningMentor() }" :class="{ 'nav-item--active': inLearningMentor() }"
> >
{{ t("a.Lernbegleitung") }} {{ t("a.Lernbegleitung") }}🗑
</router-link>
<router-link
v-if="hasLearningMentor"
data-cy="navigation-learning-mentor-link"
:to="
getLearningMentorUrl(
courseSessionsStore.currentCourseSession.course.slug
)
"
class="nav-item"
:class="{ 'nav-item--active': inLearningMentor() }"
>
{{ t("a.Lernbegleitung") }}🆕
</router-link> </router-link>
</div> </div>
</template> </template>

View File

@ -6,6 +6,7 @@ import { useRouter } from "vue-router";
import { import {
getCockpitUrl, getCockpitUrl,
getCompetenceNaviUrl, getCompetenceNaviUrl,
getLearningMentorUrl,
getLearningPathUrl, getLearningPathUrl,
getMediaCenterUrl, getMediaCenterUrl,
} from "@/utils/utils"; } from "@/utils/utils";
@ -91,6 +92,15 @@ const clickLink = (to: string | undefined) => {
{{ $t("competences.title") }} {{ $t("competences.title") }}
</button> </button>
</li> </li>
<li v-if="hasLearningMentor" class="mb-6">
<button
data-cy="navigation-mobile-mentor-link"
@click="clickLink(getLearningMentorUrl(courseSession.course.slug))"
>
{{ $t("a.Lernbegleitung") }}
</button>
</li>
<li v-if="hasMediaLibraryMenu" class="mb-6"> <li v-if="hasMediaLibraryMenu" class="mb-6">
<button <button
data-cy="medialibrary-link" data-cy="medialibrary-link"

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { getCockpitUrl } from "@/utils/utils"; import { getLearningMentorUrl } from "@/utils/utils";
import { useDashboardStore } from "@/stores/dashboard"; import { useDashboardStore } from "@/stores/dashboard";
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
@ -13,8 +13,7 @@ const dashboardStore = useDashboardStore();
<div> <div>
<router-link <router-link
class="btn-blue" class="btn-blue"
:to="getCockpitUrl(dashboardStore.currentDashboardConfig.slug)" :to="getLearningMentorUrl(dashboardStore.currentDashboardConfig.slug)"
:data-cy="`continue-course-${dashboardStore.currentDashboardConfig.id}`"
> >
{{ $t("a.Zur Lernbegleitung") }} {{ $t("a.Zur Lernbegleitung") }}
</router-link> </router-link>

View File

@ -12,8 +12,10 @@ const route = useRoute();
class="border-t-2 border-t-transparent" class="border-t-2 border-t-transparent"
:class="{ :class="{
'border-b-2 border-b-blue-900': 'border-b-2 border-b-blue-900':
route.name === 'learningMentorOverview' || // all detail pages are under overview and prefixed
route.name === 'learningMentor', // except for participants
route.name?.toString().startsWith('learningMentor') &&
route.name !== 'learningMentorParticipants',
}" }"
> >
<router-link :to="{ name: 'learningMentorOverview' }" class="block py-3"> <router-link :to="{ name: 'learningMentorOverview' }" class="block py-3">
@ -27,7 +29,7 @@ const route = useRoute();
}" }"
> >
<router-link :to="{ name: 'learningMentorParticipants' }" class="block py-3"> <router-link :to="{ name: 'learningMentorParticipants' }" class="block py-3">
{{ $t("a.Teilnehmer") }} {{ $t("a.Personen") }}
</router-link> </router-link>
</li> </li>
</ul> </ul>

View File

@ -14,11 +14,11 @@ const courseSession = useCurrentCourseSession();
const learningMentees = useLearningMentees(courseSession.value.id); const learningMentees = useLearningMentees(courseSession.value.id);
const summary = learningMentees.summary; const summary = learningMentees.summary;
const statusFilterValue = ref({ name: t("Alle"), id: "_all" }); const statusFilterValue = ref({ name: t("a.Zu erledigen"), id: "_todo" });
const statusFilter = ref([ const statusFilter = ref([
{ name: t("Alle"), id: "_all" }, { name: t("Alle"), id: "_all" },
{ name: t("a.Zu erledigen"), id: "todo" }, { name: t("a.Zu erledigen"), id: "_todo" },
]); ]);
const circleFilterValue = ref({ name: t("a.AlleCircle"), id: "_all" }); const circleFilterValue = ref({ name: t("a.AlleCircle"), id: "_all" });
@ -55,42 +55,51 @@ const filteredAssignments: Ref<Assignment[]> = computed(() => {
</script> </script>
<template> <template>
<div v-if="summary" class="bg-white"> <template v-if="summary">
<div class="flex flex-col space-x-2 lg:flex-row"> <h2 class="heading-2 mb-6 mt-6">{{ t("a.Das wurde mit dir geteilt") }}</h2>
<ItDropdownSelect <div class="bg-white">
v-model="statusFilterValue" <div class="flex flex-col lg:flex-row lg:space-x-2">
class="min-w-[10rem]" <ItDropdownSelect
:items="statusFilter" v-model="statusFilterValue"
borderless class="min-w-[10rem]"
></ItDropdownSelect> :items="statusFilter"
<ItDropdownSelect borderless
v-model="circleFilterValue" ></ItDropdownSelect>
class="min-w-[18rem]" <ItDropdownSelect
:items="circleFilter" v-model="circleFilterValue"
borderless class="min-w-[18rem]"
></ItDropdownSelect> :items="circleFilter"
borderless
></ItDropdownSelect>
</div>
<template v-if="filteredAssignments.length > 0">
<template v-for="item in filteredAssignments" :key="item.id">
<PraxisAssignmentItem
v-if="item.type === 'praxis_assignment'"
:circle-title="learningMentees.getCircleTitleById(item.circle_id)"
:pending-tasks="item.pending_evaluations"
:task-link="{
name: 'learningMentorPraxisAssignments',
params: { praxisAssignmentId: item.id },
}"
:task-title="item.title"
/>
<SelfAssignmentFeedbackAssignmentItem
v-else-if="item.type === 'self_evaluation_feedback'"
:circle-title="learningMentees.getCircleTitleById(item.circle_id)"
:pending-tasks="item.pending_evaluations"
:task-link="{
name: 'learningMentorSelfEvaluationFeedbackAssignments',
params: { learningUnitId: item.id },
}"
:task-title="item.title"
/>
</template>
</template>
<div v-else class="m-6 flex flex-row items-center bg-green-200">
<it-icon-check class="it-icon"></it-icon-check>
<p class="py-4 text-base">{{ $t("a.Du hast alles erledigt.") }}</p>
</div>
</div> </div>
<template v-for="item in filteredAssignments" :key="item.id"> </template>
<PraxisAssignmentItem
v-if="item.type === 'praxis_assignment'"
:circle-title="learningMentees.getCircleTitleById(item.circle_id)"
:pending-tasks="item.pending_evaluations"
:task-link="{
name: 'learningMentorPraxisAssignments',
params: { praxisAssignmentId: item.id },
}"
:task-title="item.title"
/>
<SelfAssignmentFeedbackAssignmentItem
v-else-if="item.type === 'self_evaluation_feedback'"
:circle-title="learningMentees.getCircleTitleById(item.circle_id)"
:pending-tasks="item.pending_evaluations"
:task-link="{
name: 'learningMentorSelfEvaluationFeedbackAssignments',
params: { learningUnitId: item.id },
}"
:task-title="item.title"
/>
</template>
</div>
</template> </template>

View File

@ -7,32 +7,35 @@ const { summary } = useLearningMentees(courseSession.value.id);
</script> </script>
<template> <template>
<div v-if="summary" class="bg-white px-4 py-2"> <div v-if="summary">
<div <h2 class="heading-2 mb-6 mt-6">{{ $t("a.Personen, die du begleitest") }}</h2>
v-for="participant in summary.participants" <div class="bg-white px-4 py-2">
:key="participant.id" <div
class="flex flex-col items-start justify-between gap-4 border-b py-2 last:border-b-0 md:flex-row md:items-center md:gap-16" v-for="participant in summary.participants"
> :key="participant.id"
<div class="flex items-center space-x-2"> class="flex flex-col items-start justify-between gap-4 border-b py-2 last:border-b-0 md:flex-row md:items-center md:gap-16"
<img
:alt="participant.last_name"
class="h-11 w-11 rounded-full"
:src="participant.avatar_url || '/static/avatars/myvbv-default-avatar.png'"
/>
<div>
<div class="text-bold">
{{ participant.first_name }}
{{ participant.last_name }}
</div>
{{ participant.email }}
</div>
</div>
<router-link
:to="{ name: 'userProfile', params: { userId: participant.id } }"
class="underline"
> >
{{ $t("cockpit.profileLink") }} <div class="flex items-center space-x-2">
</router-link> <img
:alt="participant.last_name"
class="h-11 w-11 rounded-full"
:src="participant.avatar_url || '/static/avatars/myvbv-default-avatar.png'"
/>
<div>
<div class="text-bold">
{{ participant.first_name }}
{{ participant.last_name }}
</div>
{{ participant.email }}
</div>
</div>
<router-link
:to="{ name: 'userProfile', params: { userId: participant.id } }"
class="underline"
>
{{ $t("cockpit.profileLink") }}
</router-link>
</div>
</div> </div>
</div> </div>
</template> </template>

View File

@ -23,7 +23,7 @@ export function useRouteLookups() {
} }
function inLearningMentor() { function inLearningMentor() {
const regex = new RegExp("/course/[^/]+/mentor($|/)"); const regex = new RegExp("/course/[^/]+/learning-mentor($|/)");
return regex.test(route.path); return regex.test(route.path);
} }

View File

@ -14,10 +14,7 @@ function createCourseUrl(courseSlug: string | undefined, specificSub: string): s
return "/"; return "/";
} }
if (["learn", "media", "competence", "cockpit", "mentor"].includes(specificSub)) { return `/course/${courseSlug}/${specificSub}`;
return `/course/${courseSlug}/${specificSub}`;
}
return `/course/${courseSlug}`;
} }
export function getCompetenceNaviUrl(courseSlug: string | undefined): string { export function getCompetenceNaviUrl(courseSlug: string | undefined): string {
@ -32,6 +29,10 @@ export function getLearningPathUrl(courseSlug: string | undefined): string {
return createCourseUrl(courseSlug, "learn"); return createCourseUrl(courseSlug, "learn");
} }
export function getLearningMentorUrl(courseSlug: string | undefined): string {
return createCourseUrl(courseSlug, "learning-mentor");
}
export function getCockpitUrl(courseSlug: string | undefined): string { export function getCockpitUrl(courseSlug: string | undefined): string {
return createCourseUrl(courseSlug, "cockpit"); return createCourseUrl(courseSlug, "cockpit");
} }

View File

@ -51,13 +51,6 @@ def has_course_session_preview(user, course_session_id: int):
) )
def has_expert_cockpit(user, course_session_id: int):
# FIXME: is_learning_mentor is just here WHILE we move cockpit -> learning-mentor THEN remove this!
return is_learning_mentor(user, course_session_id) or is_course_session_expert(
user, course_session_id
)
def has_media_library(user, course_session_id: int): def has_media_library(user, course_session_id: int):
if user.is_superuser: if user.is_superuser:
return True return True
@ -247,6 +240,40 @@ def has_appointments(user: User, course_session_id: int) -> bool:
return CourseSessionUser.objects.filter(course_session=course_session_id).exists() return CourseSessionUser.objects.filter(course_session=course_session_id).exists()
def has_learning_mentor(user: User, course_session_id: int) -> bool:
course_session = CourseSession.objects.get(id=course_session_id)
if course_session is None:
return False
if not course_session.course.configuration.enable_learning_mentor:
return False
if is_learning_mentor(user, course_session_id):
return True
if is_course_session_member(user, course_session_id):
return True
return False
def can_have_learning_mentors(user: User, course_session_id: int) -> bool:
if not has_learning_mentor(user, course_session_id):
return False
# limit further, since has_learning_mentor is too broad
return is_course_session_member(user, course_session_id)
def can_feedback_mentees(user: User, course_session_id: int) -> bool:
if not has_learning_mentor(user, course_session_id):
return False
# limit further, since has_learning_mentor is too broad
return is_learning_mentor(user, course_session_id)
def can_view_profile(user: User, profile_user: CourseSessionUser) -> bool: def can_view_profile(user: User, profile_user: CourseSessionUser) -> bool:
if user.is_superuser: if user.is_superuser:
return True return True
@ -291,11 +318,18 @@ def course_session_permissions(user: User, course_session_id: int) -> list[str]:
{ {
# FIXME: Just here WHILE we move cockpit -> learning-mentor THEN remove this! # FIXME: Just here WHILE we move cockpit -> learning-mentor THEN remove this!
"deprecated-mentor": is_course_session_member(user, course_session_id), "deprecated-mentor": is_course_session_member(user, course_session_id),
"learning-mentor": is_learning_mentor(user, course_session_id), # has learning mentor "tab" access?
"learning-mentor": has_learning_mentor(user, course_session_id),
"learning-mentor::edit-mentors": can_have_learning_mentors(
user, course_session_id
),
"learning-mentor::feedback-mentees": can_feedback_mentees(
user, course_session_id
),
"preview": has_course_session_preview(user, course_session_id), "preview": has_course_session_preview(user, course_session_id),
"media-library": has_media_library(user, course_session_id), "media-library": has_media_library(user, course_session_id),
"appointments": has_appointments(user, course_session_id), "appointments": has_appointments(user, course_session_id),
"expert-cockpit": has_expert_cockpit(user, course_session_id), "expert-cockpit": is_course_session_expert(user, course_session_id),
"learning-path": is_course_session_member(user, course_session_id), "learning-path": is_course_session_member(user, course_session_id),
"competence-navi": is_course_session_member(user, course_session_id), "competence-navi": is_course_session_member(user, course_session_id),
"complete-learning-content": can_complete_learning_content( "complete-learning-content": can_complete_learning_content(