This repository has been archived on 2024-02-08. You can view files and clone it, but cannot push or open issues or pull requests.
frontend/src/App.vue

224 lines
7.1 KiB
Vue

<template>
<div>
<div v-if="online">
<!-- This is a workaround to get the sw to "see" the to-be-cached version of the offline background image -->
<div class="offline" style="height: 0;width: 0;"></div>
<top-navigation v-if="userAuthenticated && (userInfo && userInfo.type === authTypes.USER)"/>
<content-auth v-if="userAuthenticated && (userInfo && userInfo.type === authTypes.USER)"/>
<content-link-share v-else-if="userAuthenticated && (userInfo && userInfo.type === authTypes.LINK_SHARE)"/>
<div v-else>
<div class="noauth-container">
<img alt="Vikunja" src="/images/logo-full.svg"/>
<div class="message is-info" v-if="motd !== ''">
<div class="message-header">
<p>Info</p>
</div>
<div class="message-body">
{{ motd }}
</div>
</div>
<router-view/>
</div>
</div>
<notification/>
</div>
<div class="app offline" v-else>
<div class="offline-message">
<h1>You are offline.</h1>
<p>Please check your network connection and try again.</p>
</div>
</div>
<transition name="fade">
<keyboard-shortcuts v-if="keyboardShortcutsActive"/>
</transition>
</div>
</template>
<script>
import router from './router'
import {mapState} from 'vuex'
import authTypes from './models/authTypes'
import Rights from './models/rights.json'
import Notification from './components/misc/notification'
import {CURRENT_LIST, IS_FULLPAGE, KEYBOARD_SHORTCUTS_ACTIVE, MENU_ACTIVE, ONLINE} from './store/mutation-types'
import KeyboardShortcuts from './components/misc/keyboard-shortcuts'
import TopNavigation from '@/components/home/topNavigation'
import ContentAuth from '@/components/home/contentAuth'
import ContentLinkShare from '@/components/home/contentLinkShare'
export default {
name: 'app',
components: {
ContentLinkShare,
ContentAuth,
TopNavigation,
KeyboardShortcuts,
Notification,
},
data() {
return {
currentDate: new Date(),
authTypes: authTypes,
}
},
beforeMount() {
// Check if the user is offline, show a message then
this.$store.commit(ONLINE, navigator.onLine)
window.addEventListener('online', () => this.$store.commit(ONLINE, navigator.onLine))
window.addEventListener('offline', () => this.$store.commit(ONLINE, navigator.onLine))
// Password reset
if (this.$route.query.userPasswordReset !== undefined) {
localStorage.removeItem('passwordResetToken') // Delete an eventually preexisting old token
localStorage.setItem('passwordResetToken', this.$route.query.userPasswordReset)
router.push({name: 'user.password-reset.reset'})
}
// Email verification
if (this.$route.query.userEmailConfirm !== undefined) {
localStorage.removeItem('emailConfirmToken') // Delete an eventually preexisting old token
localStorage.setItem('emailConfirmToken', this.$route.query.userEmailConfirm)
router.push({name: 'user.login'})
}
},
beforeCreate() {
this.$store.dispatch('config/update')
this.$store.dispatch('auth/checkAuth')
.then(() => {
// Check if the user is already logged in, if so, redirect them to the homepage
if (
!this.userAuthenticated &&
this.$route.name !== 'user.login' &&
this.$route.name !== 'user.password-reset.request' &&
this.$route.name !== 'user.password-reset.reset' &&
this.$route.name !== 'user.register' &&
this.$route.name !== 'link-share.auth'
) {
router.push({name: 'user.login'})
}
if (this.userAuthenticated && this.userInfo.type === authTypes.USER && (this.$route.params.name === 'home' || this.namespaces.length === 0)) {
this.loadNamespaces()
}
})
},
created() {
// Make sure to always load the home route when running with electron
if (this.$route.fullPath.endsWith('frontend/index.html')) {
this.$router.push({name: 'home'})
}
// Hide the menu by default on mobile
if (window.innerWidth < 770) {
this.$store.commit(MENU_ACTIVE, false)
}
// Try renewing the token every time vikunja is loaded initially
// (When opening the browser the focus event is not fired)
this.$store.dispatch('auth/renewToken')
// Check if the token is still valid if the window gets focus again to maybe renew it
window.addEventListener('focus', () => {
if (!this.userAuthenticated) {
return
}
const expiresIn = this.userInfo.exp - +new Date() / 1000
// If the token expiry is negative, it is already expired and we have no choice but to redirect
// the user to the login page
if (expiresIn < 0) {
this.$store.dispatch('auth/checkAuth')
router.push({name: 'user.login'})
return
}
// Check if the token is valid for less than 60 hours and renew if thats the case
if (expiresIn < 60 * 3600) {
this.$store.dispatch('auth/renewToken')
console.log('renewed token')
}
})
},
watch: {
// call the method again if the route changes
'$route': 'doStuffAfterRoute',
},
computed: mapState({
userInfo: state => state.auth.info,
userAvatar: state => state.auth.avatarUrl,
userAuthenticated: state => state.auth.authenticated,
motd: state => state.config.motd,
online: ONLINE,
fullpage: IS_FULLPAGE,
namespaces(state) {
return state.namespaces.namespaces.filter(n => !n.isArchived)
},
currentList: CURRENT_LIST,
background: 'background',
imprintUrl: state => state.config.legal.imprintUrl,
privacyPolicyUrl: state => state.config.legal.privacyPolicyUrl,
canWriteCurrentList: state => state.currentList.maxRight > Rights.READ,
menuActive: MENU_ACTIVE,
keyboardShortcutsActive: KEYBOARD_SHORTCUTS_ACTIVE,
}),
methods: {
logout() {
this.$store.dispatch('auth/logout')
router.push({name: 'user.login'})
},
loadNamespaces() {
this.$store.dispatch('namespaces/loadNamespaces')
},
loadNamespacesIfNeeded(e) {
if (this.userAuthenticated && (this.userInfo && this.userInfo.type === authTypes.USER) && (e.name === 'home' || this.namespaces.length === 0)) {
this.loadNamespaces()
}
},
doStuffAfterRoute(e) {
// this.setTitle('') // Reset the title if the page component does not set one itself
if (this.$store.state[IS_FULLPAGE]) {
this.$store.commit(IS_FULLPAGE, false)
}
this.loadNamespacesIfNeeded(e)
// If the menu is active on desktop, don't hide it because that would confuse the user
if (window.innerWidth < 770) {
this.$store.commit(MENU_ACTIVE, false)
}
// Reset the current list highlight in menu if the current list is not list related.
if (
this.$route.name === 'home' ||
this.$route.name === 'namespace.edit' ||
this.$route.name === 'teams.index' ||
this.$route.name === 'teams.edit' ||
this.$route.name === 'tasks.range' ||
this.$route.name === 'labels.index' ||
this.$route.name === 'migrate.start' ||
this.$route.name === 'migrate.wunderlist' ||
this.$route.name === 'user.settings' ||
this.$route.name === 'namespaces.index'
) {
this.$store.commit(CURRENT_LIST, {})
}
},
toggleFavoriteList(list) {
// The favorites pseudo list is always favorite
// Archived lists cannot be marked favorite
if (list.id === -1 || list.isArchived) {
return
}
this.$store.dispatch('lists/toggleListFavorite', list)
.catch(e => this.error(e, this))
},
},
}
</script>