Refactor course url handling

This commit is contained in:
Daniel Egger 2023-10-06 15:32:47 +02:00
parent 41ead1dad4
commit 06d284b1ce
7 changed files with 197 additions and 181 deletions

View File

@ -24,7 +24,7 @@ const { t } = useTranslation();
<div class="flex space-x-8"> <div class="flex space-x-8">
<router-link <router-link
data-cy="preview-learn-path-link" data-cy="preview-learn-path-link"
:to="getLearningPathUrl(courseSession)" :to="getLearningPathUrl(courseSession.course.slug)"
class="preview-nav-item" class="preview-nav-item"
:class="{ 'preview-nav-item--active': inLearningPath() }" :class="{ 'preview-nav-item--active': inLearningPath() }"
> >
@ -33,7 +33,7 @@ const { t } = useTranslation();
<router-link <router-link
data-cy="preview-competence-profile-link" data-cy="preview-competence-profile-link"
:to="getCompetenceNaviUrl(courseSession)" :to="getCompetenceNaviUrl(courseSession.course.slug)"
class="preview-nav-item" class="preview-nav-item"
:class="{ 'preview-nav-item--active': inCompetenceProfile() }" :class="{ 'preview-nav-item--active': inCompetenceProfile() }"
> >

View File

@ -75,7 +75,9 @@ onMounted(() => {
v-if="userStore.loggedIn" v-if="userStore.loggedIn"
:show="state.showMobileNavigationMenu" :show="state.showMobileNavigationMenu"
:course-session="courseSessionsStore.currentCourseSession" :course-session="courseSessionsStore.currentCourseSession"
:media-url="getMediaCenterUrl(courseSessionsStore.currentCourseSession)" :media-url="
getMediaCenterUrl(courseSessionsStore.currentCourseSession?.course?.slug)
"
:user="userStore" :user="userStore"
@closemodal="state.showMobileNavigationMenu = false" @closemodal="state.showMobileNavigationMenu = false"
@logout="userStore.handleLogout()" @logout="userStore.handleLogout()"
@ -142,7 +144,11 @@ onMounted(() => {
<router-link <router-link
data-cy="navigation-preview-link" data-cy="navigation-preview-link"
:to="getLearningPathUrl(courseSessionsStore.currentCourseSession)" :to="
getLearningPathUrl(
courseSessionsStore.currentCourseSession.course.slug
)
"
target="_blank" target="_blank"
class="nav-item" class="nav-item"
> >
@ -155,7 +161,11 @@ onMounted(() => {
<template v-else> <template v-else>
<router-link <router-link
data-cy="navigation-learning-path-link" data-cy="navigation-learning-path-link"
:to="getLearningPathUrl(courseSessionsStore.currentCourseSession)" :to="
getLearningPathUrl(
courseSessionsStore.currentCourseSession.course.slug
)
"
class="nav-item" class="nav-item"
:class="{ 'nav-item--active': inLearningPath() }" :class="{ 'nav-item--active': inLearningPath() }"
> >
@ -165,7 +175,9 @@ onMounted(() => {
<router-link <router-link
data-cy="navigation-competence-profile-link" data-cy="navigation-competence-profile-link"
:to=" :to="
getCompetenceNaviUrl(courseSessionsStore.currentCourseSession) getCompetenceNaviUrl(
courseSessionsStore.currentCourseSession.course.slug
)
" "
class="nav-item" class="nav-item"
:class="{ 'nav-item--active': inCompetenceProfile() }" :class="{ 'nav-item--active': inCompetenceProfile() }"
@ -180,7 +192,11 @@ onMounted(() => {
<div class="flex items-stretch justify-start space-x-8"> <div class="flex items-stretch justify-start space-x-8">
<router-link <router-link
v-if="inCourse() && courseSessionsStore.currentCourseSession" v-if="inCourse() && courseSessionsStore.currentCourseSession"
:to="getMediaCenterUrl(courseSessionsStore.currentCourseSession)" :to="
getMediaCenterUrl(
courseSessionsStore.currentCourseSession.course.slug
)
"
data-cy="medialibrary-link" data-cy="medialibrary-link"
class="nav-item-no-mobile" class="nav-item-no-mobile"
:class="{ 'nav-item--active': inMediaLibrary() }" :class="{ 'nav-item--active': inMediaLibrary() }"

View File

@ -72,7 +72,7 @@ const courseSessionsStore = useCourseSessionsStore();
<li class="mb-6"> <li class="mb-6">
<button <button
data-cy="navigation-mobile-preview-link" data-cy="navigation-mobile-preview-link"
@click="clickLink(getLearningPathUrl(courseSession))" @click="clickLink(getLearningPathUrl(courseSession.course.slug))"
> >
{{ $t("a.VorschauTeilnehmer") }} {{ $t("a.VorschauTeilnehmer") }}
</button> </button>
@ -82,7 +82,7 @@ const courseSessionsStore = useCourseSessionsStore();
<li class="mb-6"> <li class="mb-6">
<button <button
data-cy="navigation-mobile-learning-path-link" data-cy="navigation-mobile-learning-path-link"
@click="clickLink(getLearningPathUrl(courseSession))" @click="clickLink(getLearningPathUrl(courseSession.course.slug))"
> >
{{ $t("general.learningPath") }} {{ $t("general.learningPath") }}
</button> </button>
@ -90,7 +90,7 @@ const courseSessionsStore = useCourseSessionsStore();
<li class="mb-6"> <li class="mb-6">
<button <button
data-cy="navigation-mobile-competence-profile-link" data-cy="navigation-mobile-competence-profile-link"
@click="clickLink(getCompetenceNaviUrl(courseSession))" @click="clickLink(getCompetenceNaviUrl(courseSession.course.slug))"
> >
{{ $t("competences.title") }} {{ $t("competences.title") }}
</button> </button>
@ -99,7 +99,7 @@ const courseSessionsStore = useCourseSessionsStore();
<li class="mb-6"> <li class="mb-6">
<button <button
data-cy="medialibrary-link" data-cy="medialibrary-link"
@click="clickLink(getMediaCenterUrl(courseSession))" @click="clickLink(getMediaCenterUrl(courseSession.course.slug))"
> >
{{ $t("a.Mediathek") }} {{ $t("a.Mediathek") }}
</button> </button>

View File

@ -23,7 +23,7 @@ const getNextStepLink = (courseSession: CourseSession) => {
if (courseSessionsStore.hasCockpit(courseSession)) { if (courseSessionsStore.hasCockpit(courseSession)) {
return `${courseSession.course_url}/cockpit`; return `${courseSession.course_url}/cockpit`;
} }
return getLearningPathUrl(courseSession); return getLearningPathUrl(courseSession.course.slug);
}); });
}; };
</script> </script>

View File

@ -36,176 +36,178 @@ function userCountStatusForCircle(userId: string) {
<template> <template>
<div class="bg-gray-200"> <div class="bg-gray-200">
<div v-if="cockpitStore.currentCircle" class="container-large"> <div v-if="cockpitStore.circles?.length">
<div class="mb-9 flex flex-col lg:flex-row lg:items-center lg:justify-between"> <div v-if="cockpitStore.currentCircle" class="container-large">
<h1>Cockpit</h1> <div class="mb-9 flex flex-col lg:flex-row lg:items-center lg:justify-between">
<ItDropdownSelect <h1>Cockpit</h1>
:model-value="cockpitStore.currentCircle" <ItDropdownSelect
class="mt-4 w-full lg:mt-0 lg:w-96" :model-value="cockpitStore.currentCircle"
:items="cockpitStore.circles" class="mt-4 w-full lg:mt-0 lg:w-96"
@update:model-value="cockpitStore.setCurrentCourseCircleFromEvent" :items="cockpitStore.circles"
></ItDropdownSelect> @update:model-value="cockpitStore.setCurrentCourseCircleFromEvent"
</div> ></ItDropdownSelect>
<!-- Status --> </div>
<div class="mb-4 gap-4 lg:grid lg:grid-cols-3 lg:grid-rows-none"> <!-- Status -->
<div class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0"> <div class="mb-4 gap-4 lg:grid lg:grid-cols-3 lg:grid-rows-none">
<div> <div class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0">
<h3 class="heading-3 mb-4 flex items-center gap-2"> <div>
{{ $t("Trainerunterlagen") }} <h3 class="heading-3 mb-4 flex items-center gap-2">
</h3> {{ $t("Trainerunterlagen") }}
<div class="mb-4"> </h3>
{{ $t("cockpit.trainerFilesText") }} <div class="mb-4">
{{ $t("cockpit.trainerFilesText") }}
</div>
</div>
<div>
<a
href="https://vbvbern.sharepoint.com/sites/myVBV-AFA_K-CI"
class="btn-secondary min-w-min"
target="_blank"
>
{{ $t("MS Teams öffnen") }}
</a>
</div> </div>
</div> </div>
<div> <div class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0">
<a <div>
href="https://vbvbern.sharepoint.com/sites/myVBV-AFA_K-CI" <h3 class="heading-3 mb-4 flex items-center gap-2">
class="btn-secondary min-w-min" {{ $t("a.Unterlagen für Teilnehmenden") }}
target="_blank" </h3>
> <div class="mb-4">
{{ $t("MS Teams öffnen") }} {{ $t("a.Stelle deinen Lernenden zusätzliche Inhalte zur Verfügung.") }}
</a> </div>
</div> <!-- <div-->
</div> <!-- v-if="courseSessionsStore.circleDocuments.length"-->
<div class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0"> <!-- class="mb-4 flex items-center gap-x-2"-->
<div> <!-- >-->
<h3 class="heading-3 mb-4 flex items-center gap-2"> <!-- <it-icon-document />-->
{{ $t("a.Unterlagen für Teilnehmenden") }} <!-- {{ courseSessionsStore.circleDocuments.length }} {{ $t("a.Unterlagen") }}-->
</h3> <!-- </div>-->
<div class="mb-4">
{{ $t("a.Stelle deinen Lernenden zusätzliche Inhalte zur Verfügung.") }}
</div> </div>
<!-- <div--> <div>
<!-- v-if="courseSessionsStore.circleDocuments.length"--> <router-link
<!-- class="mb-4 flex items-center gap-x-2"--> :to="`/course/${props.courseSlug}/cockpit/documents`"
<!-- >--> class="btn-secondary min-w-min"
<!-- <it-icon-document />--> >
<!-- {{ courseSessionsStore.circleDocuments.length }} {{ $t("a.Unterlagen") }}--> {{ $t("a.Zum Unterlagen-Upload") }}
<!-- </div>--> </router-link>
</div>
<div>
<router-link
:to="`/course/${props.courseSlug}/cockpit/documents`"
class="btn-secondary min-w-min"
>
{{ $t("a.Zum Unterlagen-Upload") }}
</router-link>
</div>
</div>
<div class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0">
<div>
<h3 class="heading-3 mb-4 flex items-center gap-2">
{{ $t("Anwesenheitskontrolle Präsenzkurse") }}
</h3>
<div class="mb-4">
{{
$t(
"Hier überprüfst und bestätigst du die Anwesenheit deiner Teilnehmenden."
)
}}
</div> </div>
</div> </div>
<div> <div class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0">
<router-link <div>
:to="`/course/${props.courseSlug}/cockpit/attendance`" <h3 class="heading-3 mb-4 flex items-center gap-2">
class="btn-secondary min-w-min" {{ $t("Anwesenheitskontrolle Präsenzkurse") }}
> </h3>
{{ $t("Anwesenheit prüfen") }} <div class="mb-4">
</router-link> {{
$t(
"Hier überprüfst und bestätigst du die Anwesenheit deiner Teilnehmenden."
)
}}
</div>
</div>
<div>
<router-link
:to="`/course/${props.courseSlug}/cockpit/attendance`"
class="btn-secondary min-w-min"
>
{{ $t("Anwesenheit prüfen") }}
</router-link>
</div>
</div> </div>
</div> </div>
</div>
<div class="mb-4 bg-white p-6"> <div class="mb-4 bg-white p-6">
<CockpitDates></CockpitDates> <CockpitDates></CockpitDates>
</div> </div>
<SubmissionsOverview <SubmissionsOverview
:course-session="courseSession" :course-session="courseSession"
:selected-circle="cockpitStore.currentCircle.id" :selected-circle="cockpitStore.currentCircle.id"
></SubmissionsOverview> ></SubmissionsOverview>
<div class="pt-4"> <div class="pt-4">
<!-- progress --> <!-- progress -->
<div <div
v-if="courseSessionDetailResult.filterMembers().length > 0" v-if="courseSessionDetailResult.filterMembers().length > 0"
class="bg-white p-6" class="bg-white p-6"
> >
<h1 class="heading-3 mb-5">{{ $t("cockpit.progress") }}</h1> <h1 class="heading-3 mb-5">{{ $t("cockpit.progress") }}</h1>
<ul> <ul>
<ItPersonRow <ItPersonRow
v-for="csu in courseSessionDetailResult.filterMembers()" v-for="csu in courseSessionDetailResult.filterMembers()"
:key="csu.user_id" :key="csu.user_id"
:name="`${csu.first_name} ${csu.last_name}`" :name="`${csu.first_name} ${csu.last_name}`"
:avatar-url="csu.avatar_url" :avatar-url="csu.avatar_url"
> >
<template #center> <template #center>
<div <div
class="mt-2 flex w-full flex-col items-center justify-between lg:mt-0 lg:flex-row" class="mt-2 flex w-full flex-col items-center justify-between lg:mt-0 lg:flex-row"
> >
<LearningPathDiagram <LearningPathDiagram
v-if=" v-if="
learningPathStore.learningPathForUser( learningPathStore.learningPathForUser(
props.courseSlug, props.courseSlug,
csu.user_id csu.user_id
) )
" "
:learning-path=" :learning-path="
learningPathStore.learningPathForUser( learningPathStore.learningPathForUser(
props.courseSlug, props.courseSlug,
csu.user_id csu.user_id
) as LearningPath ) as LearningPath
" "
:show-circle-slugs="[cockpitStore.currentCircle.slug]" :show-circle-slugs="[cockpitStore.currentCircle.slug]"
diagram-type="singleSmall" diagram-type="singleSmall"
class="mr-4" class="mr-4"
></LearningPathDiagram> ></LearningPathDiagram>
<p class="lg:min-w-[150px]"> <p class="lg:min-w-[150px]">
{{ cockpitStore.currentCircle.title }} {{ cockpitStore.currentCircle.title }}
</p> </p>
<div class="ml-4 flex flex-row items-center"> <div class="ml-4 flex flex-row items-center">
<div class="mr-6 flex flex-row items-center"> <div class="mr-6 flex flex-row items-center">
<it-icon-smiley-thinking <it-icon-smiley-thinking
class="mr-2 inline-block h-8 w-8" class="mr-2 inline-block h-8 w-8"
></it-icon-smiley-thinking> ></it-icon-smiley-thinking>
<p class="text-bold inline-block w-6"> <p class="text-bold inline-block w-6">
{{ userCountStatusForCircle(csu.user_id).FAIL }} {{ userCountStatusForCircle(csu.user_id).FAIL }}
</p> </p>
</div>
<li class="mr-6 flex flex-row items-center">
<it-icon-smiley-happy
class="mr-2 inline-block h-8 w-8"
></it-icon-smiley-happy>
<p class="text-bold inline-block w-6">
{{ userCountStatusForCircle(csu.user_id).SUCCESS }}
</p>
</li>
<li class="flex flex-row items-center">
<it-icon-smiley-neutral
class="mr-2 inline-block h-8 w-8"
></it-icon-smiley-neutral>
<p class="text-bold inline-block w-6">
{{ userCountStatusForCircle(csu.user_id).UNKNOWN }}
</p>
</li>
</div> </div>
<li class="mr-6 flex flex-row items-center">
<it-icon-smiley-happy
class="mr-2 inline-block h-8 w-8"
></it-icon-smiley-happy>
<p class="text-bold inline-block w-6">
{{ userCountStatusForCircle(csu.user_id).SUCCESS }}
</p>
</li>
<li class="flex flex-row items-center">
<it-icon-smiley-neutral
class="mr-2 inline-block h-8 w-8"
></it-icon-smiley-neutral>
<p class="text-bold inline-block w-6">
{{ userCountStatusForCircle(csu.user_id).UNKNOWN }}
</p>
</li>
</div> </div>
</div> </template>
</template> <template #link>
<template #link> <router-link
<router-link :to="`/course/${props.courseSlug}/cockpit/profile/${csu.user_id}`"
:to="`/course/${props.courseSlug}/cockpit/profile/${csu.user_id}`" class="link w-full lg:text-right"
class="link w-full lg:text-right" >
> {{ $t("general.profileLink") }}
{{ $t("general.profileLink") }} </router-link>
</router-link> </template>
</template> </ItPersonRow>
</ItPersonRow> </ul>
</ul> </div>
</div> </div>
</div> </div>
</div> <div v-else class="container-large mt-4">
<div v-else class="container-large mt-4"> <span class="text-lg text-orange-600">
<span class="text-lg text-orange-600"> {{ $t("a.Kein Circle verfügbar oder ausgewählt.") }}
{{ $t("a.Kein Circle verfügbar oder ausgewählt.") }} </span>
</span> </div>
</div> </div>
</div> </div>
</template> </template>

View File

@ -11,6 +11,7 @@ import eventBus from "@/utils/eventBus";
import { useRouteQuery } from "@vueuse/router"; import { useRouteQuery } from "@vueuse/router";
import { computed, onUnmounted } from "vue"; import { computed, onUnmounted } from "vue";
import { getPreviousRoute } from "@/router/history"; import { getPreviousRoute } from "@/router/history";
import { getCompetenceNaviUrl } from "@/utils/utils";
log.debug("LearningContent.vue setup"); log.debug("LearningContent.vue setup");
@ -127,7 +128,7 @@ onUnmounted(() => {
<div class="mt-6 lg:mt-12"> <div class="mt-6 lg:mt-12">
{{ $t("selfEvaluation.progressText") }} {{ $t("selfEvaluation.progressText") }}
<router-link <router-link
:to="courseSession.competence_url" :to="getCompetenceNaviUrl(courseSession.course.slug)"
class="text-primary-500 underline" class="text-primary-500 underline"
> >
{{ $t("selfEvaluation.progressLink") }} {{ $t("selfEvaluation.progressLink") }}

View File

@ -1,34 +1,31 @@
import type { AssignmentType, CourseSession } from "@/types"; import type { AssignmentType } from "@/types";
import { useTranslation } from "i18next-vue"; import { useTranslation } from "i18next-vue";
export function assertUnreachable(msg: string): never { export function assertUnreachable(msg: string): never {
throw new Error("Didn't expect to get here, " + msg); throw new Error("Didn't expect to get here, " + msg);
} }
function createCourseUrl( function createCourseUrl(courseSlug: string | undefined, specificSub: string): string {
courseSession: CourseSession | undefined, if (!courseSlug) {
specificSub: string return "/";
): string {
if (!courseSession) {
return "";
} }
if (["learn", "media", "competence"].includes(specificSub)) { if (["learn", "media", "competence"].includes(specificSub)) {
return `${courseSession.course_url}/${specificSub}`; return `/course/${courseSlug}/${specificSub}`;
} }
return courseSession.course_url; return `/course/${courseSlug}`;
} }
export function getCompetenceNaviUrl(courseSession: CourseSession | undefined): string { export function getCompetenceNaviUrl(courseSlug: string | undefined): string {
return createCourseUrl(courseSession, "competence"); return createCourseUrl(courseSlug, "competence");
} }
export function getMediaCenterUrl(courseSession: CourseSession | undefined): string { export function getMediaCenterUrl(courseSlug: string | undefined): string {
return createCourseUrl(courseSession, "media"); return createCourseUrl(courseSlug, "media");
} }
export function getLearningPathUrl(courseSession: CourseSession | undefined): string { export function getLearningPathUrl(courseSlug: string | undefined): string {
return createCourseUrl(courseSession, "learn"); return createCourseUrl(courseSlug, "learn");
} }
export function getAssignmentTypeTitle(assignmentType: AssignmentType): string { export function getAssignmentTypeTitle(assignmentType: AssignmentType): string {