Compare commits
4 Commits
wip/vbv-74
...
feature/ne
| Author | SHA1 | Date |
|---|---|---|
|
|
a379650367 | |
|
|
c6e21ca059 | |
|
|
2c1129eae6 | |
|
|
75c761d62d |
|
|
@ -10,11 +10,12 @@ import {
|
||||||
} from "@/utils/utils";
|
} from "@/utils/utils";
|
||||||
import { useTranslation } from "i18next-vue";
|
import { useTranslation } from "i18next-vue";
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
|
import SelectedCourseSession from "./SelectedCourseSession.vue";
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const courseSessionsStore = useCourseSessionsStore();
|
const courseSessionsStore = useCourseSessionsStore();
|
||||||
|
|
||||||
const { inCockpit, inCompetenceProfile, inLearningMentor, inLearningPath } =
|
const { isInCockpit, inCompetenceProfile, inLearningMentor, inLearningPath } =
|
||||||
useRouteLookups();
|
useRouteLookups();
|
||||||
const {
|
const {
|
||||||
hasCompetenceNaviMenu,
|
hasCompetenceNaviMenu,
|
||||||
|
|
@ -30,13 +31,17 @@ const mentorTabTitle = computed(() =>
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div v-if="courseSessionsStore.currentCourseSession" class="hidden space-x-8 lg:flex">
|
<div
|
||||||
|
v-if="courseSessionsStore.currentCourseSession"
|
||||||
|
class="hidden space-x-8 px-10 lg:flex"
|
||||||
|
>
|
||||||
|
<SelectedCourseSession />
|
||||||
<router-link
|
<router-link
|
||||||
v-if="hasCockpitMenu"
|
v-if="hasCockpitMenu"
|
||||||
data-cy="navigation-cockpit-link"
|
data-cy="navigation-cockpit-link"
|
||||||
:to="getCockpitUrl(courseSessionsStore.currentCourseSession.course.slug)"
|
:to="getCockpitUrl(courseSessionsStore.currentCourseSession.course.slug)"
|
||||||
class="nav-item"
|
class="nav-item"
|
||||||
:class="{ 'nav-item--active': inCockpit() }"
|
:class="{ 'nav-item--active': isInCockpit }"
|
||||||
>
|
>
|
||||||
{{ t("cockpit.title") }}
|
{{ t("cockpit.title") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,22 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useRouteLookups } from "@/utils/route";
|
||||||
import { useTranslation } from "i18next-vue";
|
import { useTranslation } from "i18next-vue";
|
||||||
|
const { isInCourse } = useRouteLookups();
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="hidden flex-shrink-0 items-center lg:flex">
|
<div class="flex flex-shrink-0 items-center">
|
||||||
<div class="flex items-center">
|
<template v-if="isInCourse">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<router-link to="/" class="flex items-center border-r border-white pr-3">
|
||||||
|
<it-icon-arrow-left />
|
||||||
|
<span class="hidden text-slate-500 lg:inline">Dashboard</span>
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
<router-link to="/" class="flex">
|
<router-link to="/" class="flex">
|
||||||
<it-icon-vbv class="-ml-3 -mt-6 mr-3 h-8 w-16" />
|
<it-icon-vbv class="-ml-3 -mt-6 mr-3 h-8 w-16" />
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
@ -15,6 +25,6 @@ const { t } = useTranslation();
|
||||||
{{ t("general.title") }}
|
{{ t("general.title") }}
|
||||||
</div>
|
</div>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,7 @@ log.debug("MainNavigationBar created");
|
||||||
|
|
||||||
const courseSessionsStore = useCourseSessionsStore();
|
const courseSessionsStore = useCourseSessionsStore();
|
||||||
const { inMediaLibrary, inAppointments } = useRouteLookups();
|
const { inMediaLibrary, inAppointments } = useRouteLookups();
|
||||||
const { hasMediaLibraryMenu, hasAppointmentsMenu, hasSessionTitle } =
|
const { hasMediaLibraryMenu, hasAppointmentsMenu } = useNavigationAttributes();
|
||||||
useNavigationAttributes();
|
|
||||||
|
|
||||||
const selectedCourseSessionTitle = computed(() => {
|
|
||||||
return courseSessionsStore.currentCourseSession?.title;
|
|
||||||
});
|
|
||||||
|
|
||||||
const appointmentsUrl = computed(() => {
|
const appointmentsUrl = computed(() => {
|
||||||
const currentCourseSession = courseSessionsStore.currentCourseSession;
|
const currentCourseSession = courseSessionsStore.currentCourseSession;
|
||||||
|
|
@ -40,7 +35,6 @@ onMounted(() => {
|
||||||
<nav class="bg-blue-900 text-white">
|
<nav class="bg-blue-900 text-white">
|
||||||
<div class="mx-auto px-4 lg:px-8">
|
<div class="mx-auto px-4 lg:px-8">
|
||||||
<div class="relative flex h-16 justify-between">
|
<div class="relative flex h-16 justify-between">
|
||||||
<MobileMenuButton />
|
|
||||||
<div class="flex flex-1 items-stretch justify-start">
|
<div class="flex flex-1 items-stretch justify-start">
|
||||||
<HomeNavigation />
|
<HomeNavigation />
|
||||||
<CourseSessionNavigation />
|
<CourseSessionNavigation />
|
||||||
|
|
@ -62,7 +56,7 @@ onMounted(() => {
|
||||||
v-if="hasAppointmentsMenu"
|
v-if="hasAppointmentsMenu"
|
||||||
:to="appointmentsUrl"
|
:to="appointmentsUrl"
|
||||||
data-cy="all-duedates-link"
|
data-cy="all-duedates-link"
|
||||||
class="nav-item"
|
class="nav-item-no-mobile"
|
||||||
:class="{ 'nav-item--active': inAppointments() }"
|
:class="{ 'nav-item--active': inAppointments() }"
|
||||||
>
|
>
|
||||||
<it-icon-calendar-light class="h-8 w-8" />
|
<it-icon-calendar-light class="h-8 w-8" />
|
||||||
|
|
@ -71,22 +65,12 @@ onMounted(() => {
|
||||||
<!-- Notification Bell & Menu -->
|
<!-- Notification Bell & Menu -->
|
||||||
<NotificationButton />
|
<NotificationButton />
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="hasSessionTitle"
|
|
||||||
class="nav-item hidden items-center lg:inline-flex"
|
|
||||||
>
|
|
||||||
<div class="" data-cy="current-course-session-title">
|
|
||||||
{{ selectedCourseSessionTitle }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="nav-item">
|
<div class="nav-item">
|
||||||
<ProfileMenuButton />
|
<ProfileMenuButton />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<MobileMenuButton />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="postcss"></style>
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ const showMenu = ref(false);
|
||||||
@logout="userStore.handleLogout()"
|
@logout="userStore.handleLogout()"
|
||||||
/>
|
/>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
<div class="absolute inset-y-0 left-0 flex items-center lg:hidden">
|
<div class="inset-y-0 flex items-center lg:hidden">
|
||||||
<!-- Mobile menu button -->
|
<!-- Mobile menu button -->
|
||||||
<div data-cy="navigation-mobile-menu-button" class="flex" @click="showMenu = true">
|
<div data-cy="navigation-mobile-menu-button" class="flex" @click="showMenu = true">
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,11 @@ function popoverClick(event: Event) {
|
||||||
<AccountMenu @close="showMenu = false" />
|
<AccountMenu @close="showMenu = false" />
|
||||||
</ItFullScreenModal>
|
</ItFullScreenModal>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
<div v-if="userStore.loggedIn" class="flex items-center" data-cy="header-profile">
|
<div
|
||||||
|
v-if="userStore.loggedIn"
|
||||||
|
class="hidden items-center lg:flex"
|
||||||
|
data-cy="header-profile"
|
||||||
|
>
|
||||||
<Popover class="relative">
|
<Popover class="relative">
|
||||||
<PopoverButton @click="popoverClick($event)">
|
<PopoverButton @click="popoverClick($event)">
|
||||||
<div v-if="userStore.avatar_url">
|
<div v-if="userStore.avatar_url">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
||||||
|
import { useNavigationAttributes } from "@/utils/navigation";
|
||||||
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
const courseSessionsStore = useCourseSessionsStore();
|
||||||
|
const { hasSessionTitle } = useNavigationAttributes();
|
||||||
|
|
||||||
|
const selectedCourseSessionTitle = computed(() => {
|
||||||
|
return courseSessionsStore.currentCourseSession?.title;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div v-if="hasSessionTitle" class="nav-item hidden items-center lg:inline-flex">
|
||||||
|
<div class="" data-cy="current-course-session-title">
|
||||||
|
{{ selectedCourseSessionTitle }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -1,15 +1,18 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useCurrentCourseSession, useEvaluationWithFeedback } from "@/composables";
|
import { useCurrentCourseSession, useEvaluationWithFeedback } from "@/composables";
|
||||||
|
import {
|
||||||
|
CERTIFICATES_ROUTE,
|
||||||
|
COMPETENCE_ROUTE,
|
||||||
|
COMPETENCES_ROUTE,
|
||||||
|
SELF_EVALUATION_ROUTE,
|
||||||
|
} from "@/router/names";
|
||||||
|
import { Listbox, ListboxButton, ListboxOption, ListboxOptions } from "@headlessui/vue";
|
||||||
import * as log from "loglevel";
|
import * as log from "loglevel";
|
||||||
import { onMounted } from "vue";
|
import { onMounted } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
log.debug("CompetenceParentPage created");
|
log.debug("CompetenceParentPage created");
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
courseSlug: string;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
function routeInOverview() {
|
function routeInOverview() {
|
||||||
|
|
@ -32,19 +35,68 @@ const currentCourseSession = useCurrentCourseSession();
|
||||||
const hasEvaluationFeedback = useEvaluationWithFeedback().hasFeedback;
|
const hasEvaluationFeedback = useEvaluationWithFeedback().hasFeedback;
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
log.debug("CompetenceParentPage mounted", props.courseSlug);
|
log.debug("CompetenceParentPage mounted");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const items = [
|
||||||
|
{ id: 0, name: "Übersicht" },
|
||||||
|
{ id: 1, name: "Teilnehmer" },
|
||||||
|
{ id: 2, name: "Unterlagen" },
|
||||||
|
{ id: 3, name: "MS Teams", iconName: "it-icon-external-link" },
|
||||||
|
{ id: 4, name: "Vorschau Teilnehmer", iconName: "it-icon-external-link" },
|
||||||
|
];
|
||||||
|
const competenceRoute = {
|
||||||
|
name: COMPETENCE_ROUTE,
|
||||||
|
};
|
||||||
|
const certificatesRoute = {
|
||||||
|
name: CERTIFICATES_ROUTE,
|
||||||
|
};
|
||||||
|
const selfEvaluationRoute = {
|
||||||
|
name: SELF_EVALUATION_ROUTE,
|
||||||
|
};
|
||||||
|
const competencesRoute = {
|
||||||
|
name: COMPETENCES_ROUTE,
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="bg-gray-200">
|
<div class="bg-gray-200">
|
||||||
<nav class="border-b bg-white px-4 lg:px-8">
|
<nav class="border-b bg-white px-4 lg:px-8">
|
||||||
<ul class="flex flex-col lg:flex-row">
|
<Listbox as="div">
|
||||||
|
<div class="relative w-full">
|
||||||
|
<ListboxButton
|
||||||
|
class="relative flex w-full cursor-default flex-row items-center border bg-white py-3 pl-5 pr-10 text-left"
|
||||||
|
>
|
||||||
|
Übersicht
|
||||||
|
<span
|
||||||
|
class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"
|
||||||
|
>
|
||||||
|
<it-icon-arrow-down class="h-5 w-5" aria-hidden="true" />
|
||||||
|
</span>
|
||||||
|
</ListboxButton>
|
||||||
|
<ListboxOptions
|
||||||
|
class="absolute top-14 flex w-full cursor-default flex-col rounded-xl border-0 bg-white text-left shadow-lg"
|
||||||
|
>
|
||||||
|
<ListboxOption
|
||||||
|
v-for="item in items"
|
||||||
|
:key="item.id"
|
||||||
|
as="router-link"
|
||||||
|
class="flex w-full items-center gap-2 border-b py-3 pl-5 pr-10 last:border-b-0"
|
||||||
|
>
|
||||||
|
<router-link to="/">
|
||||||
|
{{ item.name }}
|
||||||
|
</router-link>
|
||||||
|
<component :is="item.iconName" v-if="item.iconName"></component>
|
||||||
|
</ListboxOption>
|
||||||
|
</ListboxOptions>
|
||||||
|
</div>
|
||||||
|
</Listbox>
|
||||||
|
<ul class="hidden flex-col lg:flex lg:flex-row">
|
||||||
<li
|
<li
|
||||||
class="border-t-2 border-t-transparent"
|
class="border-t-2 border-t-transparent"
|
||||||
:class="{ 'border-b-2 border-b-blue-900': routeInOverview() }"
|
:class="{ 'border-b-2 border-b-blue-900': routeInOverview() }"
|
||||||
>
|
>
|
||||||
<router-link :to="`/course/${courseSlug}/competence`" class="block py-3">
|
<router-link :to="competenceRoute" class="block py-3">
|
||||||
{{ $t("a.Übersicht") }}
|
{{ $t("a.Übersicht") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -55,10 +107,7 @@ onMounted(async () => {
|
||||||
class="border-t-2 border-t-transparent lg:ml-12"
|
class="border-t-2 border-t-transparent lg:ml-12"
|
||||||
:class="{ 'border-b-2 border-b-blue-900': routeInCompetenceCertificate() }"
|
:class="{ 'border-b-2 border-b-blue-900': routeInCompetenceCertificate() }"
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link :to="certificatesRoute" class="block py-3">
|
||||||
:to="`/course/${courseSlug}/competence/certificates`"
|
|
||||||
class="block py-3"
|
|
||||||
>
|
|
||||||
{{ $t("a.Kompetenznachweise") }}
|
{{ $t("a.Kompetenznachweise") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -69,7 +118,7 @@ onMounted(async () => {
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link
|
||||||
:to="`/course/${courseSlug}/competence/self-evaluation-and-feedback`"
|
:to="selfEvaluationRoute"
|
||||||
class="block py-3"
|
class="block py-3"
|
||||||
data-cy="self-evaluation-and-feedback-navigation-link"
|
data-cy="self-evaluation-and-feedback-navigation-link"
|
||||||
>
|
>
|
||||||
|
|
@ -84,10 +133,7 @@ onMounted(async () => {
|
||||||
class="border-t-2 border-t-transparent lg:ml-12"
|
class="border-t-2 border-t-transparent lg:ml-12"
|
||||||
:class="{ 'border-b-2 border-b-blue-900': routeInActionCompetences() }"
|
:class="{ 'border-b-2 border-b-blue-900': routeInActionCompetences() }"
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link :to="competencesRoute" class="block py-3">
|
||||||
:to="`/course/${courseSlug}/competence/competences`"
|
|
||||||
class="block py-3"
|
|
||||||
>
|
|
||||||
{{ $t("a.Handlungskompetenzen") }}
|
{{ $t("a.Handlungskompetenzen") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,12 @@ import {
|
||||||
import { addToHistory, setLastNavigationWasPush } from "@/router/history";
|
import { addToHistory, setLastNavigationWasPush } from "@/router/history";
|
||||||
import { onboardingRedirect } from "@/router/onboarding";
|
import { onboardingRedirect } from "@/router/onboarding";
|
||||||
import { createRouter, createWebHistory } from "vue-router";
|
import { createRouter, createWebHistory } from "vue-router";
|
||||||
|
import {
|
||||||
|
CERTIFICATES_ROUTE,
|
||||||
|
COMPETENCE_ROUTE,
|
||||||
|
COMPETENCES_ROUTE,
|
||||||
|
SELF_EVALUATION_ROUTE,
|
||||||
|
} from "./names";
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
|
|
@ -107,10 +113,12 @@ const router = createRouter({
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
props: true,
|
props: true,
|
||||||
|
name: COMPETENCE_ROUTE,
|
||||||
component: () => import("@/pages/competence/CompetenceIndexPage.vue"),
|
component: () => import("@/pages/competence/CompetenceIndexPage.vue"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "certificates",
|
path: "certificates",
|
||||||
|
name: CERTIFICATES_ROUTE,
|
||||||
props: true,
|
props: true,
|
||||||
component: () =>
|
component: () =>
|
||||||
import("@/pages/competence/CompetenceCertificateListPage.vue"),
|
import("@/pages/competence/CompetenceCertificateListPage.vue"),
|
||||||
|
|
@ -122,7 +130,7 @@ const router = createRouter({
|
||||||
import("@/pages/competence/CompetenceCertificateDetailPage.vue"),
|
import("@/pages/competence/CompetenceCertificateDetailPage.vue"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "selfEvaluationAndFeedback",
|
name: SELF_EVALUATION_ROUTE,
|
||||||
path: "self-evaluation-and-feedback",
|
path: "self-evaluation-and-feedback",
|
||||||
props: true,
|
props: true,
|
||||||
component: () =>
|
component: () =>
|
||||||
|
|
@ -130,6 +138,7 @@ const router = createRouter({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "competences",
|
path: "competences",
|
||||||
|
name: COMPETENCES_ROUTE,
|
||||||
props: true,
|
props: true,
|
||||||
component: () => import("@/pages/competence/ActionCompetenceListPage.vue"),
|
component: () => import("@/pages/competence/ActionCompetenceListPage.vue"),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
export const COMPETENCE_ROUTE = "competence";
|
||||||
|
export const CERTIFICATES_ROUTE = "certificates";
|
||||||
|
export const SELF_EVALUATION_ROUTE = "selfEvaluationAndFeedback";
|
||||||
|
export const COMPETENCES_ROUTE = "competences";
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { computed, ref } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
export function useRouteLookups() {
|
export function useRouteLookups() {
|
||||||
|
|
@ -7,11 +8,15 @@ export function useRouteLookups() {
|
||||||
return route.path.startsWith("/course/");
|
return route.path.startsWith("/course/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isInCourse = computed(() => inCourse());
|
||||||
|
|
||||||
function inCockpit() {
|
function inCockpit() {
|
||||||
const regex = new RegExp("/course/[^/]+/cockpit($|/)");
|
const regex = new RegExp("/course/[^/]+/cockpit($|/)");
|
||||||
return regex.test(route.path);
|
return regex.test(route.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isInCockpit = computed(() => inCockpit());
|
||||||
|
|
||||||
function inLearningPath() {
|
function inLearningPath() {
|
||||||
const regex = new RegExp("/course/[^/]+/learn($|/)");
|
const regex = new RegExp("/course/[^/]+/learn($|/)");
|
||||||
return regex.test(route.path);
|
return regex.test(route.path);
|
||||||
|
|
@ -39,7 +44,9 @@ export function useRouteLookups() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
inMediaLibrary,
|
inMediaLibrary,
|
||||||
|
isInCourse,
|
||||||
inCockpit,
|
inCockpit,
|
||||||
|
isInCockpit,
|
||||||
inLearningPath,
|
inLearningPath,
|
||||||
inCompetenceProfile,
|
inCompetenceProfile,
|
||||||
inLearningMentor,
|
inLearningMentor,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue