Changeset View
Changeset View
Standalone View
Standalone View
src/resources/vue/Widgets/Menu.vue
<template> | <template> | ||||
<nav :id="mode + '-menu'" class="navbar navbar-expand-lg navbar-light"> | <nav :id="mode + '-menu'" class="navbar navbar-expand-lg navbar-light"> | ||||
<div class="container"> | <div class="container"> | ||||
<router-link class="navbar-brand" to="/" v-html="$root.logo(mode)"></router-link> | <router-link class="navbar-brand" to="/" v-html="$root.logo(mode)"></router-link> | ||||
<button v-if="mode == 'header'" class="navbar-toggler" type="button" | <button v-if="mode == 'header'" class="navbar-toggler" type="button" | ||||
data-toggle="collapse" :data-target="'#' + mode + '-menu-navbar'" | data-toggle="collapse" :data-target="'#' + mode + '-menu-navbar'" | ||||
aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation" | aria-controls="navbar" aria-expanded="false" :aria-label="$t('menu.toggle')" | ||||
> | > | ||||
<span class="navbar-toggler-icon"></span> | <span class="navbar-toggler-icon"></span> | ||||
</button> | </button> | ||||
<div :id="mode + '-menu-navbar'" :class="'navbar' + (mode == 'header' ? ' collapse navbar-collapse' : '')"> | <div :id="mode + '-menu-navbar'" :class="'navbar' + (mode == 'header' ? ' collapse navbar-collapse' : '')"> | ||||
<ul class="navbar-nav"> | <ul class="navbar-nav"> | ||||
<li class="nav-item" v-for="item in menu()" :key="item.index"> | <li class="nav-item" v-for="item in menu" :key="item.index"> | ||||
<a v-if="item.href" :class="'nav-link link-' + item.index" :href="item.href">{{ item.title }}</a> | <a v-if="item.href" :class="'nav-link link-' + item.index" :href="item.href">{{ item.title }}</a> | ||||
<router-link v-if="item.to" | <router-link v-if="item.to" | ||||
:class="'nav-link link-' + item.index" | :class="'nav-link link-' + item.index" | ||||
active-class="active" | active-class="active" | ||||
:to="item.to" | :to="item.to" | ||||
:exact="item.exact" | :exact="item.exact" | ||||
> | > | ||||
{{ item.title }} | {{ item.title }} | ||||
</router-link> | </router-link> | ||||
</li> | </li> | ||||
<li class="nav-item" v-if="!loggedIn && !$root.isAdmin"> | <li class="nav-item" v-if="!loggedIn && !$root.isAdmin"> | ||||
<router-link class="nav-link link-signup" active-class="active" :to="{name: 'signup'}">Signup</router-link> | <router-link class="nav-link link-signup" active-class="active" :to="{name: 'signup'}">{{ $t('menu.signup') }}</router-link> | ||||
</li> | </li> | ||||
<li class="nav-item" v-if="loggedIn"> | <li class="nav-item" v-if="loggedIn"> | ||||
<router-link class="nav-link link-dashboard" active-class="active" :to="{name: 'dashboard'}">Cockpit</router-link> | <router-link class="nav-link link-dashboard" active-class="active" :to="{name: 'dashboard'}">{{ $t('menu.cockpit') }}</router-link> | ||||
</li> | </li> | ||||
<li class="nav-item" v-if="loggedIn"> | <li class="nav-item" v-if="loggedIn"> | ||||
<router-link class="nav-link menulogin link-logout" active-class="active" :to="{name: 'logout'}">Logout</router-link> | <router-link class="nav-link menulogin link-logout" active-class="active" :to="{name: 'logout'}">{{ $t('menu.logout') }}</router-link> | ||||
</li> | </li> | ||||
<li class="nav-item" v-if="!loggedIn"> | <li class="nav-item" v-if="!loggedIn"> | ||||
<router-link class="nav-link menulogin link-login" :to="{name: 'login'}">Login</router-link> | <router-link class="nav-link menulogin link-login" :to="{name: 'login'}">{{ $t('menu.login') }}</router-link> | ||||
</li> | |||||
<li v-if="languages.length > 1 && mode == 'header'" id="language-selector" class="nav-item dropdown"> | |||||
<a href="#" class="nav-link link-lang dropdown-toggle" role="button" data-toggle="dropdown">{{ getLang().toUpperCase() }}</a> | |||||
<div class="dropdown-menu dropdown-menu-right"> | |||||
<a class="dropdown-item" href="#" v-for="lang in languages" :key="lang" @click="setLang(lang)"> | |||||
{{ lang.toUpperCase() }} - {{ $t('lang.' + lang) }} | |||||
</a> | |||||
</div> | |||||
</li> | </li> | ||||
</ul> | </ul> | ||||
<div v-if="mode == 'footer'" class="footer"> | <div v-if="mode == 'footer'" class="footer"> | ||||
<div id="footer-copyright">@ Apheleia IT AG, {{ buildYear }}</div> | <div id="footer-copyright">@ Apheleia IT AG, {{ buildYear }}</div> | ||||
<div v-if="footer" id="footer-company">{{ footer }}</div> | <div v-if="footer" id="footer-company">{{ footer }}</div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</nav> | </nav> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import buildDate from '../../js/ts.js' | import buildDate from '../../build/js/ts' | ||||
import { setLang, getLang } from '../../js/locale' | |||||
export default { | export default { | ||||
data() { | |||||
return { | |||||
buildYear: buildDate.getFullYear() | |||||
} | |||||
}, | |||||
props: { | props: { | ||||
mode: { type: String, default: 'header' }, | mode: { type: String, default: 'header' }, | ||||
footer: { type: String, default: '' } | footer: { type: String, default: '' } | ||||
}, | }, | ||||
data() { | |||||
return { | |||||
buildYear: buildDate.getFullYear(), | |||||
languages: window.config['languages'] || [], | |||||
menuList: [] | |||||
} | |||||
}, | |||||
computed: { | computed: { | ||||
loggedIn() { return this.$store.state.isLoggedIn }, | loggedIn() { return this.$store.state.isLoggedIn }, | ||||
menu() { return this.menuList.filter(item => !item.footer || this.mode == 'footer') }, | |||||
route() { return this.$route.name } | route() { return this.$route.name } | ||||
}, | }, | ||||
mounted() { | mounted() { | ||||
this.menuList = this.loadMenu() | |||||
// On mobile close the menu when the menu item is clicked | // On mobile close the menu when the menu item is clicked | ||||
if (this.mode == 'header') { | if (this.mode == 'header') { | ||||
$('#header-menu .navbar').on('click', function() { $(this).removeClass('show') }) | $('#header-menu .navbar').on('click', function() { $(this).removeClass('show') }) | ||||
} | } | ||||
}, | }, | ||||
methods: { | methods: { | ||||
menu() { | loadMenu() { | ||||
let menu = [] | let menu = [] | ||||
const lang = this.getLang() | |||||
const loggedIn = this.loggedIn | const loggedIn = this.loggedIn | ||||
window.config.menu.forEach(item => { | window.config.menu.forEach(item => { | ||||
item.title = item['title-' + lang] || item['title-en'] || item.title | |||||
if (!item.location || !item.title) { | if (!item.location || !item.title) { | ||||
console.error("Invalid menu entry", item) | console.error("Invalid menu entry", item) | ||||
return | return | ||||
} | } | ||||
// TODO: Different menu for different loggedIn state | // TODO: Different menu for different loggedIn state | ||||
if (window.isAdmin && !item.admin) { | |||||
return | |||||
} else if (!window.isAdmin && item.admin === 'only') { | |||||
return | |||||
} | |||||
if (!item.footer || this.mode == 'footer') { | |||||
if (item.location.match(/^https?:/)) { | if (item.location.match(/^https?:/)) { | ||||
item.href = item.location | item.href = item.location | ||||
} else { | } else { | ||||
item.to = { path: item.location } | item.to = { path: item.location } | ||||
} | } | ||||
item.exact = item.location == '/' | item.exact = item.location == '/' | ||||
item.index = item.page || item.title.toLowerCase().replace(/\s+/g, '') | item.index = item.page || item.title.toLowerCase().replace(/\s+/g, '') | ||||
menu.push(item) | menu.push(item) | ||||
} | |||||
}) | }) | ||||
return menu | return menu | ||||
}, | |||||
getLang() { | |||||
return getLang() | |||||
}, | |||||
setLang(language) { | |||||
setLang(language) | |||||
this.menuList = this.loadMenu() | |||||
} | } | ||||
} | } | ||||
} | } | ||||
</script> | </script> |