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,
getCompetenceNaviUrl,
getLearningMentorManagementUrl,
getLearningMentorUrl,
getLearningPathUrl,
getMediaCenterUrl,
} from "@/utils/utils";
@ -109,7 +110,8 @@ const hasNotificationsMenu = computed(() => {
return userStore.loggedIn;
});
const hasLearningMentor = computed(() => {
// FIXME: Will be removed -> WIP
const hasDeprecatedLearningMentor = computed(() => {
if (!inCourse()) {
return false;
}
@ -125,9 +127,21 @@ const hasLearningMentor = computed(() => {
return false;
}
// FIXME: Use learning-mentor action instead of deprecated-mentor once we have moved everything from cockpit!
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>
<template>
@ -262,7 +276,7 @@ const hasLearningMentor = computed(() => {
</router-link>
<router-link
v-if="hasLearningMentor"
v-if="hasDeprecatedLearningMentor"
data-cy="navigation-learning-mentor-link"
:to="
getLearningMentorManagementUrl(
@ -272,7 +286,20 @@ const hasLearningMentor = computed(() => {
class="nav-item"
: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>
</div>
</template>

View File

@ -6,6 +6,7 @@ import { useRouter } from "vue-router";
import {
getCockpitUrl,
getCompetenceNaviUrl,
getLearningMentorUrl,
getLearningPathUrl,
getMediaCenterUrl,
} from "@/utils/utils";
@ -91,6 +92,15 @@ const clickLink = (to: string | undefined) => {
{{ $t("competences.title") }}
</button>
</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">
<button
data-cy="medialibrary-link"

View File

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

View File

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

View File

@ -14,11 +14,11 @@ const courseSession = useCurrentCourseSession();
const learningMentees = useLearningMentees(courseSession.value.id);
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([
{ 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" });
@ -55,42 +55,51 @@ const filteredAssignments: Ref<Assignment[]> = computed(() => {
</script>
<template>
<div v-if="summary" class="bg-white">
<div class="flex flex-col space-x-2 lg:flex-row">
<ItDropdownSelect
v-model="statusFilterValue"
class="min-w-[10rem]"
:items="statusFilter"
borderless
></ItDropdownSelect>
<ItDropdownSelect
v-model="circleFilterValue"
class="min-w-[18rem]"
:items="circleFilter"
borderless
></ItDropdownSelect>
<template v-if="summary">
<h2 class="heading-2 mb-6 mt-6">{{ t("a.Das wurde mit dir geteilt") }}</h2>
<div class="bg-white">
<div class="flex flex-col lg:flex-row lg:space-x-2">
<ItDropdownSelect
v-model="statusFilterValue"
class="min-w-[10rem]"
:items="statusFilter"
borderless
></ItDropdownSelect>
<ItDropdownSelect
v-model="circleFilterValue"
class="min-w-[18rem]"
: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>
<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>
</div>
</template>
</template>

View File

@ -7,32 +7,35 @@ const { summary } = useLearningMentees(courseSession.value.id);
</script>
<template>
<div v-if="summary" class="bg-white px-4 py-2">
<div
v-for="participant in summary.participants"
:key="participant.id"
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"
>
<div class="flex items-center space-x-2">
<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"
<div v-if="summary">
<h2 class="heading-2 mb-6 mt-6">{{ $t("a.Personen, die du begleitest") }}</h2>
<div class="bg-white px-4 py-2">
<div
v-for="participant in summary.participants"
:key="participant.id"
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"
>
{{ $t("cockpit.profileLink") }}
</router-link>
<div class="flex items-center space-x-2">
<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>
</template>

View File

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

View File

@ -14,10 +14,7 @@ function createCourseUrl(courseSlug: string | undefined, specificSub: string): s
return "/";
}
if (["learn", "media", "competence", "cockpit", "mentor"].includes(specificSub)) {
return `/course/${courseSlug}/${specificSub}`;
}
return `/course/${courseSlug}`;
return `/course/${courseSlug}/${specificSub}`;
}
export function getCompetenceNaviUrl(courseSlug: string | undefined): string {
@ -32,6 +29,10 @@ export function getLearningPathUrl(courseSlug: string | undefined): string {
return createCourseUrl(courseSlug, "learn");
}
export function getLearningMentorUrl(courseSlug: string | undefined): string {
return createCourseUrl(courseSlug, "learning-mentor");
}
export function getCockpitUrl(courseSlug: string | undefined): string {
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):
if user.is_superuser:
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()
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:
if user.is_superuser:
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!
"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),
"media-library": has_media_library(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),
"competence-navi": is_course_session_member(user, course_session_id),
"complete-learning-content": can_complete_learning_content(