Update vue router version

This commit is contained in:
Ramon Wenger 2022-03-23 18:16:11 +01:00
parent 578b563b7b
commit 6cf9457dca
12 changed files with 664 additions and 585 deletions

View File

@ -25,7 +25,7 @@
"cypress:parallel:run": "cy2 run --parallel --record --config-file cypress.frontend.json --ci-build-id " "cypress:parallel:run": "cy2 run --parallel --record --config-file cypress.frontend.json --ci-build-id "
}, },
"dependencies": { "dependencies": {
"@apollo/client": "^3.5.8", "@apollo/client": "^3.5.10",
"@babel/core": "^7.16.7", "@babel/core": "^7.16.7",
"@babel/eslint-plugin": "^7.16.5", "@babel/eslint-plugin": "^7.16.5",
"@babel/plugin-transform-runtime": "^7.5.0", "@babel/plugin-transform-runtime": "^7.5.0",
@ -46,6 +46,8 @@
"@tiptap/vue-2": "^2.0.0-beta.77", "@tiptap/vue-2": "^2.0.0-beta.77",
"@typescript-eslint/eslint-plugin": "^5.10.0", "@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0", "@typescript-eslint/parser": "^5.10.0",
"@vue/apollo-option": "^4.0.0-alpha.16",
"@vue/compiler-sfc": "3.2.30",
"@vue/compat": "3.2.31", "@vue/compat": "3.2.31",
"@vue/test-utils": "^1.3.0", "@vue/test-utils": "^1.3.0",
"@vue/vue2-jest": "^27.0.0", "@vue/vue2-jest": "^27.0.0",
@ -96,12 +98,10 @@
"uploadcare-widget": "^3.6.0", "uploadcare-widget": "^3.6.0",
"url-loader": "^1.0.1", "url-loader": "^1.0.1",
"vee-validate": "^4.5.10", "vee-validate": "^4.5.10",
"@vee-validate/rules": "^4.5.10", "vue": "3.2.30",
"vue": "^3.2.31",
"vue-apollo": "^3.1.0",
"vue-loader": "^16.8.3", "vue-loader": "^16.8.3",
"vue-matomo": "^4.1.0", "vue-matomo": "^4.1.0",
"vue-router": "^3.5.3", "vue-router": "^4.0.14",
"vue-scrollto": "^2.20.0", "vue-scrollto": "^2.20.0",
"vue-style-loader": "^3.0.1", "vue-style-loader": "^3.0.1",
"vue-vimeo-player": "^0.2.2", "vue-vimeo-player": "^0.2.2",

View File

@ -1,5 +1,8 @@
<template> <template>
<router-link :to="to" data-cy="back-link" class="sub-navigation-item back-link"> <router-link
:to="to"
class="sub-navigation-item back-link"
>
<chevron-left class="back-link__icon sub-navigation-item__icon" /> <chevron-left class="back-link__icon sub-navigation-item__icon" />
{{ fullTitle }} {{ fullTitle }}
</router-link> </router-link>
@ -36,7 +39,11 @@ export default {
to() { to() {
switch (this.type) { switch (this.type) {
case 'topic': case 'topic':
if (this.slug) {
return {name: 'topic', params: {topicSlug: this.slug}}; return {name: 'topic', params: {topicSlug: this.slug}};
} else {
return {};
}
case 'module': case 'module':
return {name: MODULE_PAGE}; return {name: MODULE_PAGE};
case 'portfolio': case 'portfolio':

View File

@ -1,6 +1,10 @@
<template> <template>
<transition name="fade"> <transition name="fade">
<a class="scroll-up" v-if="scroll > 200" @click="scrollTop"> <a
class="scroll-up"
v-if="scroll>200"
@click="scrollTop"
>
<arrow-up class="scroll-up__icon" /> <arrow-up class="scroll-up__icon" />
</a> </a>
</transition> </transition>
@ -11,12 +15,12 @@ const ArrowUp = () => import(/* webpackChunkName: "icons" */ '@/components/icons
export default { export default {
components: { components: {
ArrowUp, ArrowUp
}, },
data() { data() {
return { return {
scroll: 0, scroll: 0
}; };
}, },
@ -34,7 +38,7 @@ export default {
methods: { methods: {
scrollTop() { scrollTop() {
document.scrollingElement.scrollTop = 0; document.scrollingElement.scrollTop = 0;
}, }
}, },
}; };
</script> </script>
@ -60,14 +64,15 @@ export default {
height: 50px; height: 50px;
fill: $color-brand; fill: $color-brand;
} }
} }
.fade-enter-active, .fade-enter-active, .fade-leave-active {
.fade-leave-active { transition: opacity .3s;
transition: opacity 0.3s;
} }
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ { .fade-enter-from, .fade-leave-to /* .fade-leave-active below version 2.1.8 */
{
opacity: 0; opacity: 0;
} }
</style> </style>

View File

@ -1,8 +1,18 @@
<template> <template>
<transition name="slide"> <transition name="slide">
<div class="navigation-sidebar" v-if="sidebar.navigation" v-click-outside="close"> <div
<content-navigation :is-sidebar="true" class="navigation-sidebar__main" /> class="navigation-sidebar"
<div class="navigation-sidebar__close-button" @click="close"> v-if="sidebar.navigation"
v-click-outside="close"
>
<content-navigation
:is-sidebar="true"
class="navigation-sidebar__main"
/>
<div
class="navigation-sidebar__close-button"
@click="close"
>
<cross class="navigation-sidebar__close-icon" /> <cross class="navigation-sidebar__close-icon" />
</div> </div>
</div> </div>
@ -21,20 +31,21 @@ export default {
components: { components: {
ContentNavigation, ContentNavigation,
Cross, Cross
}, },
methods: { methods: {
close() { close() {
this.closeSidebar('navigation'); this.closeSidebar('navigation');
}
}, },
},
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import '@/styles/_variables.scss'; @import "@/styles/_variables.scss";
@import '@/styles/_mixins.scss'; @import "@/styles/_mixins.scss";
$desktop-width: 285px; $desktop-width: 285px;
@ -56,10 +67,10 @@ $desktop-width: 285px;
grid-template-columns: 1fr 50px; grid-template-columns: 1fr 50px;
grid-template-rows: 50px max-content auto 100px; grid-template-rows: 50px max-content auto 100px;
grid-template-areas: 'm m' 'm m' 's s' 's s'; grid-template-areas: "m m" "m m" "s s" "s s";
&--with-subnavigation { &--with-subnavigation {
grid-template-areas: 'm m' 'm m' 'sub sub' 's s'; grid-template-areas: "m m" "m m" "sub sub" "s s";
} }
height: 100vh; height: 100vh;
@ -87,13 +98,11 @@ $desktop-width: 285px;
} }
.slide { .slide {
&-enter-active, &-enter-active, &-leave-active {
&-leave-active {
transition: left 0.2s; transition: left 0.2s;
} }
&-enter, &-enter-from, &-leave-to {
&-leave-to {
left: -100vw; left: -100vw;
@include desktop { @include desktop {
left: -$desktop-width; left: -$desktop-width;

View File

@ -1,5 +1,9 @@
<template> <template>
<div :class="componentClass" :data-scrollto="component.id" data-cy="content-component"> <div
:class="componentClass"
:data-scrollto="component.id"
data-cy="content-component"
>
<bookmark-actions <bookmark-actions
:bookmarked="bookmarked" :bookmarked="bookmarked"
:note="note" :note="note"
@ -9,105 +13,97 @@
@edit-note="editNote" @edit-note="editNote"
@bookmark="bookmarkContent(component.id, !bookmarked)" @bookmark="bookmarkContent(component.id, !bookmarked)"
/> />
<component v-bind="component" :parent="parent" :is="component.type" /> <component
v-bind="component"
:parent="parent"
:is="component.type"
/>
</div> </div>
</template> </template>
<script> <script>
import {constructContentComponentBookmarkMutation} from '@/helpers/update-content-bookmark-mutation'; import {constructContentComponentBookmarkMutation} from '@/helpers/update-content-bookmark-mutation';
import {defineAsyncComponent} from 'vue';
const TextBlock = () => import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/TextBlock'); const TextBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/TextBlock'));
const InstrumentWidget = () => const InstrumentWidget = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/InstrumentWidget'));
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/InstrumentWidget'); const ImageBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/ImageBlock'));
const ImageBlock = () => import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/ImageBlock'); const ImageUrlBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/ImageUrlBlock'));
const ImageUrlBlock = () => const VideoBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/VideoBlock'));
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/ImageUrlBlock'); const LinkBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/LinkBlock'));
const VideoBlock = () => import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/VideoBlock'); const DocumentBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/DocumentBlock'));
const LinkBlock = () => import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/LinkBlock'); const CmsDocumentBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/CmsDocumentBlock'));
const DocumentBlock = () => const InfogramBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/InfogramBlock'));
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/DocumentBlock'); const ThinglinkBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/ThinglinkBlock'));
const CmsDocumentBlock = () => const GeniallyBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/GeniallyBlock'));
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/CmsDocumentBlock'); const SubtitleBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/SubtitleBlock'));
const InfogramBlock = () => const SectionTitleBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/SectionTitleBlock'));
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/InfogramBlock'); const ContentListBlock = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/ContentListBlock'));
const ThinglinkBlock = () => const ModuleRoomSlug = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/ModuleRoomSlug'));
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/ThinglinkBlock'); const Assignment = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/assignment/Assignment'));
const GeniallyBlock = () => const Survey = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/SurveyBlock'));
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/GeniallyBlock'); const Solution = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/Solution'));
const SubtitleBlock = () => const Instruction = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/content-blocks/Instruction'));
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/SubtitleBlock'); const BookmarkActions = defineAsyncComponent(() => import(/* webpackChunkName: "content-components" */'@/components/notes/BookmarkActions'));
const SectionTitleBlock = () =>
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/SectionTitleBlock');
const ContentListBlock = () =>
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/ContentListBlock');
const ModuleRoomSlug = () =>
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/ModuleRoomSlug');
const Assignment = () =>
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/assignment/Assignment');
const Survey = () => import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/SurveyBlock');
const Solution = () => import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/Solution');
const Instruction = () =>
import(/* webpackChunkName: "content-components" */ '@/components/content-blocks/Instruction');
const BookmarkActions = () => import(/* webpackChunkName: "content-components" */ '@/components/notes/BookmarkActions');
export default { export default {
props: { props: {
component: { component: {
type: Object, type: Object,
default: () => ({}), default: () => ({})
}, },
parent: { parent: {
type: Object, type: Object,
default: () => ({}), default: () => ({})
}, },
bookmarks: { bookmarks: {
type: Array, type: Array,
default: () => [], default: () => ([])
}, },
notes: { notes: {
type: Array, type: Array,
default: () => [], default: () => ([])
}, },
root: { root: {
type: String, type: String,
default: '', default: ''
}, },
editMode: { editMode: {
type: Boolean, type: Boolean,
default: false, default: false
}, }
}, },
components: { components: {
text_block: TextBlock, 'text_block': TextBlock,
basic_knowledge: InstrumentWidget, // for legacy 'basic_knowledge': InstrumentWidget, // for legacy
instrument: InstrumentWidget, 'instrument': InstrumentWidget,
image_block: ImageBlock, 'image_block': ImageBlock,
image_url_block: ImageUrlBlock, 'image_url_block': ImageUrlBlock,
video_block: VideoBlock, 'video_block': VideoBlock,
link_block: LinkBlock, 'link_block': LinkBlock,
document_block: DocumentBlock, 'document_block': DocumentBlock,
infogram_block: InfogramBlock, 'infogram_block': InfogramBlock,
genially_block: GeniallyBlock, 'genially_block': GeniallyBlock,
subtitle: SubtitleBlock, 'subtitle': SubtitleBlock,
section_title: SectionTitleBlock, 'section_title': SectionTitleBlock,
content_list: ContentListBlock, 'content_list': ContentListBlock,
module_room_slug: ModuleRoomSlug, 'module_room_slug': ModuleRoomSlug,
thinglink_block: ThinglinkBlock, 'thinglink_block': ThinglinkBlock,
cms_document_block: CmsDocumentBlock, 'cms_document_block': CmsDocumentBlock,
Survey, Survey,
Solution, Solution,
Instruction, Instruction,
Assignment, Assignment,
BookmarkActions, BookmarkActions
}, },
computed: { computed: {
bookmarked() { bookmarked() {
return this.bookmarks && !!this.bookmarks.find((bookmark) => bookmark.uuid === this.component.id); return this.bookmarks && !!this.bookmarks.find(bookmark => bookmark.uuid === this.component.id);
}, },
note() { note() {
const bookmark = this.bookmarks && this.bookmarks.find((bookmark) => bookmark.uuid === this.component.id); const bookmark = this.bookmarks && this.bookmarks.find(bookmark => bookmark.uuid === this.component.id);
return bookmark && bookmark.note; return bookmark && bookmark.note;
}, },
showBookmarkActions() { showBookmarkActions() {
@ -119,19 +115,18 @@ export default {
classes.push('content-component--bookmarked'); classes.push('content-component--bookmarked');
} }
return classes; return classes;
}, }
}, },
methods: { methods: {
addNote(id) { addNote(id) {
const type = Object.prototype.hasOwnProperty.call(this.parent, '__typename') const type = Object.prototype.hasOwnProperty.call(this.parent, '__typename')
? this.parent.__typename ? this.parent.__typename : 'ContentBlockNode';
: 'ContentBlockNode';
this.$store.dispatch('addNote', { this.$store.dispatch('addNote', {
content: id, content: id,
type, type,
block: this.root, block: this.root
}); });
}, },
editNote() { editNote() {
@ -139,18 +134,19 @@ export default {
}, },
bookmarkContent(uuid, bookmarked) { bookmarkContent(uuid, bookmarked) {
this.$apollo.mutate(constructContentComponentBookmarkMutation(uuid, bookmarked, this.parent, this.root)); this.$apollo.mutate(constructContentComponentBookmarkMutation(uuid, bookmarked, this.parent, this.root));
}, }
}, }
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '~styles/helpers'; @import "~styles/helpers";
.content-component { .content-component {
position: relative; position: relative;
&--bookmarked { &--bookmarked {
} }
&--subtitle { &--subtitle {

View File

@ -1,15 +1,34 @@
<template> <template>
<!-- eslint-disable vue/no-v-html --> <!-- eslint-disable vue/no-v-html -->
<div class="solution" data-cy="solution"> <div
<a class="solution__toggle" data-cy="show-solution" @click="toggle" class="solution"
data-cy="solution"
>
<a
class="solution__toggle"
data-cy="show-solution"
@click="toggle"
>Lösung >Lösung
<template v-if="!visible">anzeigen</template> <template v-if="!visible">anzeigen</template>
<template v-else>ausblenden</template> <template v-else>ausblenden</template>
</a> </a>
<transition name="fade"> <transition name="fade">
<div class="solution__hidden fade" v-if="visible"> <div
<p class="solution__text solution-text" data-cy="solution-text" v-html="sanitizedText" /> class="solution__hidden fade"
<cms-document-block :solution="true" class="solution__document" :value="value.document" v-if="value.document" /> v-if="visible"
>
<p
class="solution__text solution-text"
data-cy="solution-text"
v-html="sanitizedText"
/>
<cms-document-block
:solution="true"
class="solution__document"
:value="value.document"
v-if="value.document"
/>
</div> </div>
</transition> </transition>
</div> </div>
@ -44,7 +63,7 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import '~styles/helpers'; @import "~styles/helpers";
.solution { .solution {
display: grid; display: grid;
@ -67,12 +86,12 @@ export default {
font-size: toRem(18px); font-size: toRem(18px);
color: $color-silver-dark; color: $color-silver-dark;
:deep(p) { /deep/ p {
font-size: toRem(18px); font-size: toRem(18px);
color: $color-silver-dark; color: $color-silver-dark;
} }
:deep(ul) { /deep/ ul {
padding-left: $medium-spacing; padding-left: $medium-spacing;
> li { > li {
@ -85,10 +104,10 @@ export default {
.fade-enter-active, .fade-enter-active,
.fade-leave-active { .fade-leave-active {
transition: opacity 0.3s; transition: opacity .3s;
} }
.fade-enter, .fade-enter-from,
.fade-leave-active { .fade-leave-active {
opacity: 0; opacity: 0;
} }

View File

@ -5,6 +5,7 @@
:slug="module.topic.slug" :slug="module.topic.slug"
class="module-navigation__topic-link" class="module-navigation__topic-link"
type="topic" type="topic"
v-if="module.topic"
/> />
<div class="module-navigation__module-content" v-if="false"> <div class="module-navigation__module-content" v-if="false">
<!-- Do not display this for now, might be used later again though --> <!-- Do not display this for now, might be used later again though -->

View File

@ -15,9 +15,17 @@
ref="avatarImage" ref="avatarImage"
/> />
</transition> </transition>
<img :src="avatarUrl" class="avatar__fake-image" ref="fakeImage" /> <img
:src="avatarUrl"
class="avatar__fake-image"
ref="fakeImage"
>
<div class="avatar__edit" v-if="editable" @click="closeSidebar"> <div
class="avatar__edit"
v-if="editable"
@click="closeSidebar"
>
<router-link :to="{name: 'profile'}"> <router-link :to="{name: 'profile'}">
<pen-icon /> <pen-icon />
</router-link> </router-link>
@ -34,20 +42,20 @@ const PenIcon = () => import(/* webpackChunkName: "icons" */ '@/components/icons
export default { export default {
props: { props: {
avatarUrl: { avatarUrl: {
type: String, type: String
}, },
iconHighlighted: {}, iconHighlighted: {},
editable: { editable: {
default: false, default: false
}, }
}, },
components: { components: {
DefaultAvatar, DefaultAvatar,
PenIcon, PenIcon
}, },
data() { data() {
return { return {
isAvatarLoaded: false, isAvatarLoaded: false
}; };
}, },
mounted() { mounted() {
@ -66,17 +74,17 @@ export default {
mutation: TOGGLE_SIDEBAR, mutation: TOGGLE_SIDEBAR,
variables: { variables: {
sidebar: { sidebar: {
profile: false, profile: false
}, }
}, }
}); });
}, }
}, }
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import '~styles/helpers'; @import "~styles/helpers";
$max-width: 100%; $max-width: 100%;
@ -130,12 +138,10 @@ $max-width: 100%;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.12); box-shadow: 0 3px 10px rgba(0, 0, 0, 0.12);
} }
.fade-leave-active, .fade-leave-active, .show-enter-active {
.show-enter-active { transition: opacity .5s;
transition: opacity 0.5s;
} }
.fade-leave-to, .fade-leave-to, .show-enter-from {
.show-enter {
opacity: 0; opacity: 0;
} }

View File

@ -1,31 +1,69 @@
<template> <template>
<transition name="slide"> <transition name="slide">
<div class="profile-sidebar" data-cy="sidebar" v-if="sidebar.profile" v-click-outside="close"> <div
<a class="profile-sidebar__close-link" data-cy="close-profile-sidebar-link" @click="close"> class="profile-sidebar"
data-cy="sidebar"
v-if="sidebar.profile"
v-click-outside="close"
>
<a
class="profile-sidebar__close-link"
data-cy="close-profile-sidebar-link"
@click="close"
>
<cross class="profile-sidebar__close-icon" /> <cross class="profile-sidebar__close-icon" />
</a> </a>
<div class="profile-sidebar__section"> <div class="profile-sidebar__section">
<profile-widget class="profile-sidebar__item" /> <profile-widget class="profile-sidebar__item" />
<div class="profile-sidebar__item" @click="close"> <div
<router-link to="/me/activity" class="profile-sidebar__link"> Meine Aktivitäten </router-link> class="profile-sidebar__item"
@click="close"
>
<router-link
to="/me/activity"
class="profile-sidebar__link"
>
Meine Aktivitäten
</router-link>
</div> </div>
<div class="profile-sidebar__item" v-if="me.isTeacher && !me.readOnly" @click="close"> <div
<router-link :to="myTeamPage" data-cy="my-team-link" class="profile-sidebar__link"> Mein Team </router-link> class="profile-sidebar__item"
v-if="me.isTeacher && !me.readOnly"
@click="close"
>
<router-link
:to="myTeamPage"
data-cy="my-team-link"
class="profile-sidebar__link"
>
Mein Team
</router-link>
</div> </div>
</div> </div>
<div class="profile-sidebar__section"> <div class="profile-sidebar__section">
<div class="profile-sidebar__item"> <div class="profile-sidebar__item">
<class-selection-widget /> <class-selection-widget />
<div @click="close"> <div @click="close">
<router-link :to="{ name: 'my-class' }" data-cy="class-list-link" class="profile-sidebar__link"> <router-link
:to="{name: 'my-class'}"
data-cy="class-list-link"
class="profile-sidebar__link"
>
Klassenliste Klassenliste
</router-link> </router-link>
</div> </div>
</div> </div>
</div> </div>
<div class="profile-sidebar__section"> <div class="profile-sidebar__section">
<div class="profile-sidebar__item" @click="close"> <div
<router-link :to="{ name: 'join-class' }" data-cy="join-class-link" class="profile-sidebar__link"> class="profile-sidebar__item"
@click="close"
>
<router-link
:to="{name:'join-class'}"
data-cy="join-class-link"
class="profile-sidebar__link"
>
Zugangscode Zugangscode
</router-link> </router-link>
</div> </div>
@ -49,6 +87,7 @@ import { MY_TEAM } from '@/router/me.names';
const Cross = () => import(/* webpackChunkName: "icons" */'@/components/icons/CrossIcon'); const Cross = () => import(/* webpackChunkName: "icons" */'@/components/icons/CrossIcon');
export default { export default {
mixins: [sidebar, me], mixins: [sidebar, me],
components: { components: {
@ -75,7 +114,7 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import '~styles/helpers'; @import "~styles/helpers";
$desktop-width: 333px; $desktop-width: 333px;
@ -133,13 +172,11 @@ $desktop-width: 333px;
} }
.slide { .slide {
&-enter-active, &-enter-active, &-leave-active {
&-leave-active {
transition: right 0.2s; transition: right 0.2s;
} }
&-enter, &-enter-from, &-leave-to {
&-leave-to {
right: -100vw; right: -100vw;
@include desktop { @include desktop {
right: -$desktop-width; right: -$desktop-width;

View File

@ -1,8 +1,7 @@
import '@babel/polyfill'; import '@babel/polyfill';
import {createApp, inject} from 'vue'; import {createApp} from 'vue';
import VueVimeoPlayer from 'vue-vimeo-player'; import VueVimeoPlayer from 'vue-vimeo-player';
import apolloClientFactory from './graphql/client'; import apolloClientFactory from './graphql/client';
import VueApollo from 'vue-apollo';
import App from './App.vue'; import App from './App.vue';
import { postLoginRedirectUrlKey, router } from './router'; import { postLoginRedirectUrlKey, router } from './router';
import store from '@/store/index'; import store from '@/store/index';
@ -14,13 +13,14 @@ import VueModal from '@/plugins/modal';
import VueRemoveEdges from '@/plugins/edges'; import VueRemoveEdges from '@/plugins/edges';
import VueMatomo from 'vue-matomo'; import VueMatomo from 'vue-matomo';
import VueLogger from 'vuejs3-logger'; import VueLogger from 'vuejs3-logger';
import { createApolloProvider } from '@vue/apollo-option';
import { joiningClass, loginRequired, unauthorizedAccess } from '@/router/guards'; import { joiningClass, loginRequired, unauthorizedAccess } from '@/router/guards';
import flavorPlugin from '@/plugins/flavor'; import flavorPlugin from '@/plugins/flavor';
const publicApolloClient = apolloClientFactory('/api/graphql-public/', null); const publicApolloClient = apolloClientFactory('/api/graphql-public/', null);
const privateApolloClient = apolloClientFactory('/api/graphql/', networkErrorCallback); const privateApolloClient = apolloClientFactory('/api/graphql/', networkErrorCallback);
const apolloProvider = new VueApollo({ const apolloProvider = createApolloProvider({
clients: { clients: {
publicClient: publicApolloClient, publicClient: publicApolloClient,
}, },
@ -39,7 +39,6 @@ const isProduction = process.env.NODE_ENV === 'production';
app.use(VueModal); app.use(VueModal);
app.use(VueRemoveEdges); app.use(VueRemoveEdges);
app.use(VueApollo);
app.use(VueVimeoPlayer); app.use(VueVimeoPlayer);
app.use(VueLogger, { app.use(VueLogger, {
isEnabled: true, isEnabled: true,
@ -47,6 +46,8 @@ app.use(VueLogger, {
stringifyArguments: false, stringifyArguments: false,
showConsoleColors: true, showConsoleColors: true,
}); });
app.use(apolloProvider);
app.use(router);
// VueScrollTo.setDefaults({ // VueScrollTo.setDefaults({
// duration: 500, // duration: 500,

View File

@ -1,4 +1,4 @@
import { Route } from 'vue-router'; import {RouteLocationNormalized} from "vue-router";
function getCookieValue(cookieName: string) { function getCookieValue(cookieName: string) {
// https://stackoverflow.com/questions/5639346/what-is-the-shortest-function-for-reading-a-cookie-by-name-in-javascript // https://stackoverflow.com/questions/5639346/what-is-the-shortest-function-for-reading-a-cookie-by-name-in-javascript
@ -6,16 +6,16 @@ function getCookieValue(cookieName: string) {
return cookieValue ? cookieValue.pop() : ''; return cookieValue ? cookieValue.pop() : '';
} }
export function loginRequired(to: Route) { export function loginRequired(to: RouteLocationNormalized) {
// public pages have the meta.public property set to true // public pages have the meta.public property set to true
const isPublic = to.meta && to.meta.public; const isPublic = to.meta && to.meta.public;
return !isPublic; return !isPublic;
} }
export function unauthorizedAccess(to: Route) { export function unauthorizedAccess(to: RouteLocationNormalized) {
return loginRequired(to) && getCookieValue('loginStatus') !== 'true'; return loginRequired(to) && getCookieValue('loginStatus') !== 'true';
} }
export function joiningClass(to: Route) { export function joiningClass(to: RouteLocationNormalized) {
return to.name && (to.name === 'join-class' || to.name === 'licenseActivation'); return to.name && (to.name === 'join-class' || to.name === 'licenseActivation');
} }

View File

@ -1,6 +1,4 @@
import Vue from 'vue'; import {createRouter, createWebHistory} from 'vue-router';
import Router from 'vue-router';
import moduleRoutes from './module.routes'; import moduleRoutes from './module.routes';
import portfolioRoutes from './portfolio.routes'; import portfolioRoutes from './portfolio.routes';
@ -23,13 +21,13 @@ const news = () => import(/* webpackChunkName: "news" */ '@/pages/news');
const surveyPage = () => import(/* webpackChunkName: "survey" */'@/pages/survey'); const surveyPage = () => import(/* webpackChunkName: "survey" */'@/pages/survey');
const styleGuidePage = () => import('@/pages/styleguide.vue'); const styleGuidePage = () => import('@/pages/styleguide');
const joinClass = () => import('@/pages/joinClass.vue'); const joinClass = () => import('@/pages/joinClass');
const topic = () => import('@/pages/topic-page.vue'); const topic = () => import('@/pages/topic-page');
const p404 = () => import('@/pages/p404.vue'); const p404 = () => import('@/pages/p404');
const submission = () => import('@/pages/studentSubmission.vue'); const submission = () => import('@/pages/studentSubmission');
const postLoginRedirectUrlKey = 'postLoginRedirectionUrl'; const postLoginRedirectUrlKey = 'postLoginRedirectionUrl';
@ -76,7 +74,7 @@ const routes = [
}, },
{ {
path: '/oauth-redirect', path: '/oauth-redirect',
redirect: (to) => { redirect: to => {
switch (to.query.state) { switch (to.query.state) {
case EMAIL_NOT_VERIFIED_STATE: case EMAIL_NOT_VERIFIED_STATE:
return '/verify-email'; return '/verify-email';
@ -98,24 +96,24 @@ const routes = [
{ {
path: '/not-found', path: '/not-found',
name: 'not-found', name: 'not-found',
...notFoundRoute, ...notFoundRoute
}, },
{ {
path: '*', path: '/:pathMatch(.*)*',
...notFoundRoute, ...notFoundRoute
}, },
]; ];
Vue.use(Router);
const router = new Router({ const router = createRouter({
routes, routes,
history: createWebHistory(),
mode: 'history', mode: 'history',
scrollBehavior(to, from, savedPosition) { scrollBehavior(to, from, savedPosition) {
if (savedPosition) { if (savedPosition) {
return savedPosition; return savedPosition;
} }
return { x: 0, y: 0 }; return {left: 0, top: 0};
}, },
}); });