diff --git a/client/package.json b/client/package.json index 8c608b45..1831a831 100644 --- a/client/package.json +++ b/client/package.json @@ -25,7 +25,7 @@ "cypress:parallel:run": "cy2 run --parallel --record --config-file cypress.frontend.json --ci-build-id " }, "dependencies": { - "@apollo/client": "^3.5.8", + "@apollo/client": "^3.5.10", "@babel/core": "^7.16.7", "@babel/eslint-plugin": "^7.16.5", "@babel/plugin-transform-runtime": "^7.5.0", @@ -46,6 +46,8 @@ "@tiptap/vue-2": "^2.0.0-beta.77", "@typescript-eslint/eslint-plugin": "^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/test-utils": "^1.3.0", "@vue/vue2-jest": "^27.0.0", @@ -96,12 +98,10 @@ "uploadcare-widget": "^3.6.0", "url-loader": "^1.0.1", "vee-validate": "^4.5.10", - "@vee-validate/rules": "^4.5.10", - "vue": "^3.2.31", - "vue-apollo": "^3.1.0", + "vue": "3.2.30", "vue-loader": "^16.8.3", "vue-matomo": "^4.1.0", - "vue-router": "^3.5.3", + "vue-router": "^4.0.14", "vue-scrollto": "^2.20.0", "vue-style-loader": "^3.0.1", "vue-vimeo-player": "^0.2.2", diff --git a/client/src/components/BackLink.vue b/client/src/components/BackLink.vue index 0fb0651f..89613070 100644 --- a/client/src/components/BackLink.vue +++ b/client/src/components/BackLink.vue @@ -1,68 +1,75 @@ diff --git a/client/src/components/ScrollUp.vue b/client/src/components/ScrollUp.vue index 10fd05fb..b031cdef 100644 --- a/client/src/components/ScrollUp.vue +++ b/client/src/components/ScrollUp.vue @@ -1,73 +1,78 @@ diff --git a/client/src/components/book-navigation/NavigationSidebar.vue b/client/src/components/book-navigation/NavigationSidebar.vue index 5ca4ed74..6b015508 100644 --- a/client/src/components/book-navigation/NavigationSidebar.vue +++ b/client/src/components/book-navigation/NavigationSidebar.vue @@ -1,8 +1,18 @@ diff --git a/client/src/components/content-blocks/ContentComponent.vue b/client/src/components/content-blocks/ContentComponent.vue index 9a9e9b60..93177354 100644 --- a/client/src/components/content-blocks/ContentComponent.vue +++ b/client/src/components/content-blocks/ContentComponent.vue @@ -1,5 +1,9 @@ diff --git a/client/src/components/content-blocks/Solution.vue b/client/src/components/content-blocks/Solution.vue index 287e9114..ac08d40d 100644 --- a/client/src/components/content-blocks/Solution.vue +++ b/client/src/components/content-blocks/Solution.vue @@ -1,95 +1,114 @@ diff --git a/client/src/components/modules/ModuleNavigation.vue b/client/src/components/modules/ModuleNavigation.vue index 54d4cc81..250edb26 100644 --- a/client/src/components/modules/ModuleNavigation.vue +++ b/client/src/components/modules/ModuleNavigation.vue @@ -5,6 +5,7 @@ :slug="module.topic.slug" class="module-navigation__topic-link" type="topic" + v-if="module.topic" />
diff --git a/client/src/components/profile/Avatar.vue b/client/src/components/profile/Avatar.vue index ee7ea5f2..94772cd5 100644 --- a/client/src/components/profile/Avatar.vue +++ b/client/src/components/profile/Avatar.vue @@ -2,23 +2,31 @@
- + -
- +
+
@@ -26,121 +34,119 @@ diff --git a/client/src/components/profile/ProfileSidebar.vue b/client/src/components/profile/ProfileSidebar.vue index 0244e4e7..bd1d9a61 100644 --- a/client/src/components/profile/ProfileSidebar.vue +++ b/client/src/components/profile/ProfileSidebar.vue @@ -1,31 +1,69 @@ diff --git a/client/src/main.js b/client/src/main.js index 7a10cf2d..817a23b9 100644 --- a/client/src/main.js +++ b/client/src/main.js @@ -1,8 +1,7 @@ import '@babel/polyfill'; -import {createApp, inject} from 'vue'; +import {createApp} from 'vue'; import VueVimeoPlayer from 'vue-vimeo-player'; import apolloClientFactory from './graphql/client'; -import VueApollo from 'vue-apollo'; import App from './App.vue'; import { postLoginRedirectUrlKey, router } from './router'; import store from '@/store/index'; @@ -14,13 +13,14 @@ import VueModal from '@/plugins/modal'; import VueRemoveEdges from '@/plugins/edges'; import VueMatomo from 'vue-matomo'; import VueLogger from 'vuejs3-logger'; +import { createApolloProvider } from '@vue/apollo-option'; import { joiningClass, loginRequired, unauthorizedAccess } from '@/router/guards'; import flavorPlugin from '@/plugins/flavor'; const publicApolloClient = apolloClientFactory('/api/graphql-public/', null); const privateApolloClient = apolloClientFactory('/api/graphql/', networkErrorCallback); -const apolloProvider = new VueApollo({ +const apolloProvider = createApolloProvider({ clients: { publicClient: publicApolloClient, }, @@ -39,7 +39,6 @@ const isProduction = process.env.NODE_ENV === 'production'; app.use(VueModal); app.use(VueRemoveEdges); -app.use(VueApollo); app.use(VueVimeoPlayer); app.use(VueLogger, { isEnabled: true, @@ -47,6 +46,8 @@ app.use(VueLogger, { stringifyArguments: false, showConsoleColors: true, }); +app.use(apolloProvider); +app.use(router); // VueScrollTo.setDefaults({ // duration: 500, diff --git a/client/src/router/guards.ts b/client/src/router/guards.ts index 69c7e6ac..9bf105d3 100644 --- a/client/src/router/guards.ts +++ b/client/src/router/guards.ts @@ -1,4 +1,4 @@ -import { Route } from 'vue-router'; +import {RouteLocationNormalized} from "vue-router"; function getCookieValue(cookieName: string) { // 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() : ''; } -export function loginRequired(to: Route) { +export function loginRequired(to: RouteLocationNormalized) { // public pages have the meta.public property set to true const isPublic = to.meta && to.meta.public; return !isPublic; } -export function unauthorizedAccess(to: Route) { +export function unauthorizedAccess(to: RouteLocationNormalized) { 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'); } diff --git a/client/src/router/index.js b/client/src/router/index.js index e2dc764c..f5013956 100644 --- a/client/src/router/index.js +++ b/client/src/router/index.js @@ -1,6 +1,4 @@ -import Vue from 'vue'; - -import Router from 'vue-router'; +import {createRouter, createWebHistory} from 'vue-router'; import moduleRoutes from './module.routes'; import portfolioRoutes from './portfolio.routes'; @@ -10,26 +8,26 @@ import authRoutes from './auth.routes'; import roomRoutes from './room.routes'; import store from '@/store/index'; -import { LAYOUT_SIMPLE } from '@/router/core.constants'; -import { EMAIL_NOT_VERIFIED_STATE, NO_VALID_LICENSE_STATE, SUCCESS_STATE } from './oauth.names'; +import {LAYOUT_SIMPLE} from '@/router/core.constants'; +import {EMAIL_NOT_VERIFIED_STATE, NO_VALID_LICENSE_STATE, SUCCESS_STATE} from './oauth.names'; import start from '@/pages/start'; -const instrument = () => import(/* webpackChunkName: "instruments" */ '@/pages/instrument'); -const instrumentOverview = () => import(/* webpackChunkName: "instruments" */ '@/pages/instrumentOverview'); +const instrument = () => import(/* webpackChunkName: "instruments" */'@/pages/instrument'); +const instrumentOverview = () => import(/* webpackChunkName: "instruments" */'@/pages/instrumentOverview'); -const article = () => import(/* webpackChunkName: "news" */ '@/pages/article'); -const news = () => import(/* webpackChunkName: "news" */ '@/pages/news'); +const article = () => import(/* webpackChunkName: "news" */'@/pages/article'); +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 joinClass = () => import('@/pages/joinClass.vue'); +const styleGuidePage = () => import('@/pages/styleguide'); +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 submission = () => import('@/pages/studentSubmission.vue'); +const p404 = () => import('@/pages/p404'); +const submission = () => import('@/pages/studentSubmission'); const postLoginRedirectUrlKey = 'postLoginRedirectionUrl'; @@ -52,22 +50,22 @@ const routes = [ ...onboardingRoutes, ...portfolioRoutes, ...meRoutes, - { path: '/article/:slug', name: 'article', component: article, meta: { layout: LAYOUT_SIMPLE } }, + {path: '/article/:slug', name: 'article', component: article, meta: {layout: LAYOUT_SIMPLE}}, { path: '/instruments/', name: 'instrument-overview', component: instrumentOverview, }, - { path: '/instrument/:slug', name: 'instrument', component: instrument, meta: { layout: LAYOUT_SIMPLE } }, - { path: '/submission/:id', name: 'submission', component: submission, meta: { layout: LAYOUT_SIMPLE } }, - { path: '/topic/:topicSlug', name: 'topic', component: topic, alias: '/book/topic/:topicSlug' }, - { path: '/join-class', name: 'join-class', component: joinClass, meta: { layout: LAYOUT_SIMPLE } }, + {path: '/instrument/:slug', name: 'instrument', component: instrument, meta: {layout: LAYOUT_SIMPLE}}, + {path: '/submission/:id', name: 'submission', component: submission, meta: {layout: LAYOUT_SIMPLE}}, + {path: '/topic/:topicSlug', name: 'topic', component: topic, alias: '/book/topic/:topicSlug'}, + {path: '/join-class', name: 'join-class', component: joinClass, meta: {layout: LAYOUT_SIMPLE}}, { path: '/survey/:id', component: surveyPage, name: 'survey', props: true, - meta: { layout: LAYOUT_SIMPLE }, + meta: {layout: LAYOUT_SIMPLE}, }, { path: '/news', @@ -76,7 +74,7 @@ const routes = [ }, { path: '/oauth-redirect', - redirect: (to) => { + redirect: to => { switch (to.query.state) { case EMAIL_NOT_VERIFIED_STATE: return '/verify-email'; @@ -94,28 +92,28 @@ const routes = [ } }, }, - { path: '/styleguide', component: styleGuidePage }, + {path: '/styleguide', component: styleGuidePage}, { path: '/not-found', name: 'not-found', - ...notFoundRoute, + ...notFoundRoute }, { - path: '*', - ...notFoundRoute, + path: '/:pathMatch(.*)*', + ...notFoundRoute }, ]; -Vue.use(Router); -const router = new Router({ +const router = createRouter({ routes, + history: createWebHistory(), mode: 'history', scrollBehavior(to, from, savedPosition) { if (savedPosition) { return savedPosition; } - return { x: 0, y: 0 }; + return {left: 0, top: 0}; }, }); @@ -124,4 +122,4 @@ router.afterEach(() => { store.dispatch('showMobileNavigation', false); }); -export { router, postLoginRedirectUrlKey }; +export {router, postLoginRedirectUrlKey};