import '@babel/polyfill' import Vue from 'vue' import axios from 'axios' import VueAxios from 'vue-axios' import VueVimeoPlayer from 'vue-vimeo-player' import apolloClientFactory from './graphql/client' import VueApollo from 'vue-apollo' import App from './App' import router from './router' import store from '@/store/index' import VueScrollTo from 'vue-scrollto'; import VueAnalytics from 'vue-analytics'; import {Validator, install as VeeValidate} from 'vee-validate/dist/vee-validate.minimal.esm.js'; import {required, min} from 'vee-validate/dist/rules.esm.js'; import veeDe from 'vee-validate/dist/locale/de'; import {dateFilter} from './filters/date-filter'; import autoGrow from '@/directives/auto-grow' import clickOutside from '@/directives/click-outside' import ME_QUERY from '@/graphql/gql/meQuery.gql'; Vue.config.productionTip = false; // TODO: Move into a separate project as a plugin // function getRidOfEdges(collection) { if (typeof collection === 'object' && collection && !Array.isArray(collection)) { let newObj = {}; for (const k in collection) { if (k === 'edges') { return collection.edges.map(edge => getRidOfEdges(edge.node)); } else { newObj[k] = getRidOfEdges(collection[k]); if (newObj[k]) { // delete newObj[k]['__typename'] } } } return newObj } else { return collection } } Object.defineProperty(Vue.prototype, '$getRidOfEdges', {value: getRidOfEdges}); Vue.use(VueApollo); Vue.use(VueAxios, axios); Vue.use(VueVimeoPlayer); Vue.use(VueScrollTo, { duration: 500, easing: 'ease-out', offset: -50 }); if (process.env.GOOGLE_ANALYTICS_ID) { Vue.use(VueAnalytics, { id: process.env.GOOGLE_ANALYTICS_ID, router }); console.log(process.env.GOOGLE_ANALYTICS_ID); } Vue.directive('click-outside', clickOutside); Vue.directive('auto-grow', autoGrow); const publicApolloClient = apolloClientFactory('/api/graphql-public/'); const privateApolloClient = apolloClientFactory('/api/graphql/'); const apolloProvider = new VueApollo({ clients: { publicClient: publicApolloClient }, defaultClient: privateApolloClient }); Validator.extend('required', required); Validator.extend('min', min); const dict = { custom: { oldPassword: { required: 'Dein aktuelles Passwort fehlt' }, newPassword: { required: 'Dein neues Passwort fehlt', min: 'Das neue Passwort muss mindestens 8 Zeichen lang sein' } } }; Validator.localize('de', veeDe) Validator.localize('de', dict) // https://github.com/baianat/vee-validate/issues/51 Validator.extend('strongPassword', { getMessage: field => 'Das Passwort muss Grossbuchstaben, Zahlen und Sonderzeichen beinhalten', validate: value => { const strongRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*?(),.":{}|<>+])(?=.{8,})/; return strongRegex.test(value); } }); Validator.extend('email', { getMessage: field => 'Bitte geben Sie eine gülitge E-Mail an', validate: value => { const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/; return emailRegex.test(value); } }); Vue.use(VeeValidate, { locale: 'de' }); Vue.filter('date', dateFilter); /* guards */ function getCookieValue(cookieName) { // https://stackoverflow.com/questions/5639346/what-is-the-shortest-function-for-reading-a-cookie-by-name-in-javascript let cookieValue = document.cookie.match('(^|[^;]+)\\s*' + cookieName + '\\s*=\\s*([^;]+)'); return cookieValue ? cookieValue.pop() : ''; } function loginRequired(to) { // public pages have the meta.public property set to true return !to.hasOwnProperty('meta') || !to.meta.hasOwnProperty('public') || !to.meta.public; } function unauthorizedAccess(to) { return loginRequired(to) && getCookieValue('loginStatus') !== 'true'; } function redirectStudentsWithoutClass() { return privateApolloClient.query({ query: ME_QUERY, }).then(({data}) => data.me.schoolClasses.edges.length === 0 && data.me.permissions.length === 0); } router.beforeEach(async (to, from, next) => { // handle logout if (to.path === '/logout') { privateApolloClient.resetStore(); next({name: 'login'}); return } if (unauthorizedAccess(to)) { const redirectUrl = `/login?redirect=${to.path}`; next(redirectUrl); return } if (to.name !== 'noClass' && loginRequired(to) && await redirectStudentsWithoutClass()) { next({name: 'noClass'}) return } next(); }); /* eslint-disable no-new */ new Vue({ el: '#app', store, router, provide: apolloProvider.provide(), render: h => h(App) });