2020-11-01 18:36:00 +01:00
|
|
|
<template>
|
|
|
|
<div :class="{'is-active': menuActive}" class="namespace-container">
|
|
|
|
<div class="menu top-menu">
|
|
|
|
<router-link :to="{name: 'home'}" class="logo">
|
|
|
|
<img alt="Vikunja" src="/images/logo-full.svg"/>
|
|
|
|
</router-link>
|
|
|
|
<ul class="menu-list">
|
|
|
|
<li>
|
|
|
|
<router-link :to="{ name: 'home'}">
|
|
|
|
<span class="icon">
|
|
|
|
<icon icon="calendar"/>
|
|
|
|
</span>
|
|
|
|
Overview
|
|
|
|
</router-link>
|
|
|
|
</li>
|
|
|
|
<li>
|
2020-11-22 18:05:25 +01:00
|
|
|
<router-link :to="{ name: 'tasks.range'}">
|
2020-11-01 18:36:00 +01:00
|
|
|
<span class="icon">
|
|
|
|
<icon :icon="['far', 'calendar-alt']"/>
|
|
|
|
</span>
|
2020-11-22 18:05:25 +01:00
|
|
|
Upcoming
|
2020-11-01 18:36:00 +01:00
|
|
|
</router-link>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<router-link :to="{ name: 'namespaces.index'}">
|
|
|
|
<span class="icon">
|
|
|
|
<icon icon="layer-group"/>
|
|
|
|
</span>
|
|
|
|
Namespaces & Lists
|
|
|
|
</router-link>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<router-link :to="{ name: 'labels.index'}">
|
|
|
|
<span class="icon">
|
|
|
|
<icon icon="tags"/>
|
|
|
|
</span>
|
|
|
|
Labels
|
|
|
|
</router-link>
|
|
|
|
</li>
|
2020-12-23 21:28:32 +01:00
|
|
|
<li>
|
|
|
|
<router-link :to="{ name: 'teams.index'}">
|
|
|
|
<span class="icon">
|
|
|
|
<icon icon="users"/>
|
|
|
|
</span>
|
|
|
|
Teams
|
|
|
|
</router-link>
|
|
|
|
</li>
|
2020-11-01 18:36:00 +01:00
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
|
2020-11-12 20:57:39 +01:00
|
|
|
<aside class="menu namespaces-lists loader-container" :class="{'is-loading': loading}">
|
2020-11-01 18:36:00 +01:00
|
|
|
<template v-for="n in namespaces">
|
2021-04-19 23:56:00 +02:00
|
|
|
<div :key="n.id" class="namespace-title" :class="{'has-menu': n.id > 0}">
|
2021-02-20 16:28:45 +01:00
|
|
|
<span
|
|
|
|
@click="toggleLists(n.id)"
|
2020-11-01 18:36:00 +01:00
|
|
|
class="menu-label"
|
2021-01-14 22:40:13 +01:00
|
|
|
v-tooltip="n.title + ' (' + n.lists.filter(l => !l.isArchived).length + ')'">
|
2020-11-01 18:36:00 +01:00
|
|
|
<span class="name">
|
|
|
|
<span
|
|
|
|
:style="{ backgroundColor: n.hexColor }"
|
|
|
|
class="color-bubble"
|
|
|
|
v-if="n.hexColor !== ''">
|
|
|
|
</span>
|
2021-01-14 22:40:13 +01:00
|
|
|
{{ n.title }} ({{ n.lists.filter(l => !l.isArchived).length }})
|
2020-11-01 18:36:00 +01:00
|
|
|
</span>
|
2021-02-20 16:28:45 +01:00
|
|
|
</span>
|
2021-04-19 23:56:00 +02:00
|
|
|
<a
|
|
|
|
class="icon is-small toggle-lists-icon"
|
|
|
|
:class="{'active': typeof listsVisible[n.id] !== 'undefined' ? listsVisible[n.id] : true}"
|
2021-05-19 17:26:05 +02:00
|
|
|
@click="toggleLists(n.id)"
|
|
|
|
>
|
2021-04-19 23:56:00 +02:00
|
|
|
<icon icon="chevron-down"/>
|
|
|
|
</a>
|
2021-01-30 17:17:04 +01:00
|
|
|
<namespace-settings-dropdown :namespace="n" v-if="n.id > 0"/>
|
2020-11-01 18:36:00 +01:00
|
|
|
</div>
|
2021-04-19 22:36:31 +02:00
|
|
|
<div :key="n.id + 'child'" class="more-container" v-if="typeof listsVisible[n.id] !== 'undefined' ? listsVisible[n.id] : true">
|
2020-11-01 18:36:00 +01:00
|
|
|
<ul class="menu-list can-be-hidden">
|
|
|
|
<template v-for="l in n.lists">
|
|
|
|
<!-- This is a bit ugly but vue wouldn't want to let me filter this - probably because the lists
|
|
|
|
are nested inside of the namespaces makes it a lot harder.-->
|
|
|
|
<li :key="l.id" v-if="!l.isArchived">
|
|
|
|
<router-link
|
|
|
|
class="list-menu-link"
|
|
|
|
:class="{'router-link-exact-active': currentList.id === l.id}"
|
|
|
|
:to="{ name: 'list.index', params: { listId: l.id} }"
|
|
|
|
tag="span"
|
|
|
|
>
|
|
|
|
<span
|
|
|
|
:style="{ backgroundColor: l.hexColor }"
|
|
|
|
class="color-bubble"
|
|
|
|
v-if="l.hexColor !== ''">
|
|
|
|
</span>
|
|
|
|
<span class="list-menu-title">
|
|
|
|
{{ l.title }}
|
|
|
|
</span>
|
|
|
|
<span
|
|
|
|
:class="{'is-favorite': l.isFavorite}"
|
|
|
|
@click.stop="toggleFavoriteList(l)"
|
|
|
|
class="favorite">
|
|
|
|
<icon icon="star" v-if="l.isFavorite"/>
|
|
|
|
<icon :icon="['far', 'star']" v-else/>
|
|
|
|
</span>
|
|
|
|
</router-link>
|
2021-05-19 17:26:05 +02:00
|
|
|
<list-settings-dropdown :list="l" v-if="l.id > 0"/>
|
|
|
|
<span class="list-setting-spacer" v-else></span>
|
2020-11-01 18:36:00 +01:00
|
|
|
</li>
|
|
|
|
</template>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</aside>
|
|
|
|
<a class="menu-bottom-link" href="https://vikunja.io" target="_blank">Powered by Vikunja</a>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
import {mapState} from 'vuex'
|
2021-01-21 23:33:16 +01:00
|
|
|
import {CURRENT_LIST, MENU_ACTIVE, LOADING, LOADING_MODULE} from '@/store/mutation-types'
|
2021-01-30 17:17:04 +01:00
|
|
|
import ListSettingsDropdown from '@/components/list/list-settings-dropdown'
|
|
|
|
import NamespaceSettingsDropdown from '@/components/namespace/namespace-settings-dropdown.vue'
|
2020-11-01 18:36:00 +01:00
|
|
|
|
|
|
|
export default {
|
|
|
|
name: 'navigation',
|
2021-02-20 16:28:45 +01:00
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
listsVisible: {},
|
|
|
|
}
|
|
|
|
},
|
2021-01-30 17:17:04 +01:00
|
|
|
components: {
|
|
|
|
ListSettingsDropdown,
|
|
|
|
NamespaceSettingsDropdown,
|
|
|
|
},
|
2020-11-01 18:36:00 +01:00
|
|
|
computed: mapState({
|
2021-05-26 17:39:57 +02:00
|
|
|
namespaces: state => state.namespaces.namespaces.filter(n => !n.isArchived),
|
2020-11-01 18:36:00 +01:00
|
|
|
currentList: CURRENT_LIST,
|
|
|
|
background: 'background',
|
|
|
|
menuActive: MENU_ACTIVE,
|
2021-01-09 15:24:06 +01:00
|
|
|
loading: state => state[LOADING] && state[LOADING_MODULE] === 'namespaces',
|
2020-11-01 18:36:00 +01:00
|
|
|
}),
|
|
|
|
beforeCreate() {
|
|
|
|
this.$store.dispatch('namespaces/loadNamespaces')
|
2021-02-20 16:28:45 +01:00
|
|
|
.then(namespaces => {
|
|
|
|
namespaces.forEach(n => {
|
2021-04-19 22:36:31 +02:00
|
|
|
if (typeof this.listsVisible[n.id] === 'undefined') {
|
|
|
|
this.$set(this.listsVisible, n.id, true)
|
|
|
|
}
|
2021-02-20 16:28:45 +01:00
|
|
|
})
|
|
|
|
})
|
2020-11-01 18:36:00 +01:00
|
|
|
},
|
|
|
|
created() {
|
2020-12-10 14:52:35 +01:00
|
|
|
window.addEventListener('resize', this.resize)
|
2020-11-01 18:36:00 +01:00
|
|
|
},
|
2020-12-17 12:45:26 +01:00
|
|
|
mounted() {
|
|
|
|
this.resize()
|
|
|
|
},
|
2020-11-01 18:36:00 +01:00
|
|
|
methods: {
|
|
|
|
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)
|
2021-06-22 22:07:57 +02:00
|
|
|
.catch(e => this.error(e))
|
2020-11-01 18:36:00 +01:00
|
|
|
},
|
2020-12-10 14:52:35 +01:00
|
|
|
resize() {
|
|
|
|
// Hide the menu by default on mobile
|
|
|
|
if (window.innerWidth < 770) {
|
|
|
|
this.$store.commit(MENU_ACTIVE, false)
|
|
|
|
} else {
|
|
|
|
this.$store.commit(MENU_ACTIVE, true)
|
|
|
|
}
|
|
|
|
},
|
2021-02-20 16:28:45 +01:00
|
|
|
toggleLists(namespaceId) {
|
|
|
|
this.$set(this.listsVisible, namespaceId, !this.listsVisible[namespaceId] ?? false)
|
|
|
|
},
|
2020-11-01 18:36:00 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
</script>
|
2021-05-19 17:26:05 +02:00
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
.list-setting-spacer {
|
|
|
|
width: 32px;
|
|
|
|
flex-shrink: 0;
|
|
|
|
}
|
|
|
|
</style>
|