vikunja-frontend/src/App.vue

254 lines
5.9 KiB
Vue
Raw Normal View History

2018-08-28 22:50:22 +02:00
<template>
2018-09-07 08:42:17 +02:00
<div id="app" class="container">
2018-09-09 17:33:24 +02:00
<nav class="navbar" role="navigation" aria-label="main navigation" v-if="user.authenticated">
<div class="navbar-menu">
<div class="navbar-brand">
<div class="navbar-item logo">
<img src="logo-full.svg"/>
</div>
2018-09-09 17:23:06 +02:00
</div>
2018-09-09 17:33:24 +02:00
<div class="navbar-end">
<span class="navbar-item">{{user.infos.username}}</span>
<span class="navbar-item image">
<img :src="gravatar()" class="is-rounded" alt=""/>
2018-09-09 17:23:06 +02:00
</span>
2018-09-09 17:33:24 +02:00
<a v-on:click="logout()" class="navbar-item is-right logout-icon">
<span class="icon is-medium">
<icon icon="sign-out-alt" size="2x"/>
</span>
</a>
</div>
2018-09-09 17:23:06 +02:00
</div>
</nav>
2018-09-07 08:42:17 +02:00
<div class="column is-centered">
<div class="box" v-if="user.authenticated">
<div class="container">
<div class="columns">
2018-09-09 19:09:46 +02:00
<div class="column is-3">
<div class="buttons">
<a class="button is-success">
<span class="icon is-small">
<icon icon="plus"/>
</span>
New Namespace
</a>
<a class="button is-success">
<span class="icon is-small">
<icon icon="list-ol"/>
</span>
New List
</a>
</div>
2018-09-07 08:42:17 +02:00
<aside class="menu">
2018-09-07 22:44:07 +02:00
<p class="menu-label" v-if="loading">Loading...</p>
2018-09-07 08:42:17 +02:00
<template v-for="n in namespaces">
2018-09-07 22:44:07 +02:00
<p class="menu-label" :key="n.id">
2018-09-07 08:42:17 +02:00
{{n.name}}
</p>
2018-09-07 22:44:07 +02:00
<ul class="menu-list" :key="n.id + 'child'">
<li v-for="l in n.lists" :key="l.id">
2018-09-08 23:33:09 +02:00
<router-link :to="{ name: 'showList', params: { id: l.id} }">{{l.title}}</router-link>
2018-09-07 22:44:07 +02:00
</li>
2018-09-07 08:42:17 +02:00
</ul>
</template>
</aside>
</div>
2018-09-09 19:09:46 +02:00
<div class="column">
2018-09-07 08:42:17 +02:00
<router-view/>
</div>
</div>
</div>
</div>
<div v-else>
<router-view/>
</div>
</div>
2018-09-08 21:43:16 +02:00
<notifications position="bottom left" />
</div>
2018-08-28 22:50:22 +02:00
</template>
<script>
2018-09-07 08:42:17 +02:00
import auth from './auth'
import {HTTP} from './http-common'
2018-09-08 21:43:16 +02:00
import message from './message'
2018-09-07 08:42:17 +02:00
export default {
2018-09-07 08:42:17 +02:00
name: 'app',
data() {
return {
user: auth.user,
loading: false,
namespaces: [],
}
},
created() {
if (this.user.authenticated) {
this.loadNamespaces()
}
2018-09-07 08:42:17 +02:00
},
watch: {
// call the method again if the route changes
'$route': 'loadNamespacesIfNeeded'
},
2018-09-07 08:42:17 +02:00
methods: {
logout() {
auth.logout()
},
2018-09-09 17:23:06 +02:00
gravatar() {
return 'https://www.gravatar.com/avatar/' + this.user.infos.avatar + '?s=50'
},
2018-09-07 08:42:17 +02:00
loadNamespaces() {
this.loading = true
this.namespaces = []
HTTP.get(`namespaces`, {headers: {'Authorization': 'Bearer ' + localStorage.getItem('token')}})
.then(response => {
2018-09-07 22:44:07 +02:00
let nps = response.data
2018-09-07 08:42:17 +02:00
2018-09-07 22:44:07 +02:00
// Loop through the namespaces and get their lists
for (const n in nps) {
2018-09-07 08:42:17 +02:00
2018-09-07 22:44:07 +02:00
this.namespaces.push(nps[n])
2018-09-07 08:42:17 +02:00
2018-09-07 22:44:07 +02:00
HTTP.get(`namespaces/` + nps[n].id + `/lists`, {headers: {'Authorization': 'Bearer ' + localStorage.getItem('token')}})
2018-09-07 08:42:17 +02:00
.then(response => {
2018-09-07 22:44:07 +02:00
// This adds a new element "list" to our object which contains all lists
this.$set(this.namespaces[n], 'lists', response.data)
2018-09-07 08:42:17 +02:00
})
.catch(e => {
2018-09-08 21:43:16 +02:00
this.handleError(e)
2018-09-07 08:42:17 +02:00
})
}
this.loading = false
})
.catch(e => {
2018-09-08 21:43:16 +02:00
this.handleError(e)
2018-09-07 08:42:17 +02:00
})
},
loadNamespacesIfNeeded(e){
if (this.user.authenticated && e.name === 'home') {
this.loadNamespaces()
}
},
2018-09-08 21:43:16 +02:00
handleError(e) {
this.loading = false
message.error(e, this)
}
2018-09-07 08:42:17 +02:00
},
}
2018-08-28 22:50:22 +02:00
</script>
2018-09-09 17:33:36 +02:00
<style lang="scss">
@import url('/fonts/fonts.css');
2018-09-08 23:33:09 +02:00
*, *:focus, *:active{
outline: none;
}
2018-09-06 20:15:49 +02:00
body {
background: #f5f5f5;
min-height: 100vh;
}
2018-09-08 23:33:09 +02:00
2018-09-09 17:33:36 +02:00
h1,h2,h3,h4,h5,h6{
font-family: 'Quicksand', sans-serif;
font-weight: 400 !important;
}
2018-09-08 23:33:09 +02:00
/* spinner */
.fullscreen-loader-wrapper {
position: fixed;
background: rgba(250,250,250,0.8);
z-index: 5;
top: 0;
bottom: 0;
left: 0;
right: 0;
position: absolute;
width: 78%;
height: 100%;
margin: -1em auto;
}
.full-loader-wrapper{
background: rgba(250,250,250,0.8);
position: absolute;
width: 78%;
height: 100%;
margin: -1em auto;
}
.half-circle-spinner, .half-circle-spinner * {
box-sizing: border-box;
}
.half-circle-spinner {
width: 60px;
height: 60px;
border-radius: 100%;
position: relative;
left: calc(50% - 30px);
top: calc(50% - 30px);
}
.half-circle-spinner .circle {
content: "";
position: absolute;
width: 100%;
height: 100%;
border-radius: 100%;
border: calc(60px / 10) solid transparent;
}
.half-circle-spinner .circle.circle-1 {
border-top-color: #4CAF50;
animation: half-circle-spinner-animation 1s infinite;
}
.half-circle-spinner .circle.circle-2 {
border-bottom-color: #4CAF50;
animation: half-circle-spinner-animation 1s infinite alternate;
}
@keyframes half-circle-spinner-animation {
0% {
transform: rotate(0deg);
}
100%{
transform: rotate(360deg);
}
}
2018-09-09 17:23:06 +02:00
/* Logout-icon */
.logout-icon {
padding-right: 2em !important;
}
/* Navbar */
.navbar{
background: none !important;
2018-09-09 17:33:24 +02:00
padding-top: 0.5rem;
2018-09-09 17:23:06 +02:00
}
.logo {
padding-left: 2rem !important;
img {
max-height: 3rem !important;
margin-right: 1rem;
}
}
2018-09-09 19:09:46 +02:00
/* Buttons icons */
.button .icon.is-small{
margin-right: 0.05rem !important;
}
2018-08-28 22:50:22 +02:00
</style>