<template> <div> <v-navigation-drawer fixed clipped app permanent :mini-variant="mini" > <v-toolbar> <v-list> <v-list-tile> <v-list-tile-action v-if="mini"> <v-btn icon @click.native.stop="mini = !mini"> <v-icon>chevron_right</v-icon> </v-btn> </v-list-tile-action> <v-list-tile-content class="title" > <slot name="header"></slot> </v-list-tile-content> <v-list-tile-action v-if="!mini"> <v-btn icon @click.native.stop="mini = !mini"> <v-icon>chevron_left</v-icon> </v-btn> </v-list-tile-action> </v-list-tile> </v-list> </v-toolbar> <slot name="sidebar-content"></slot> <div class="sidebar-footer"> <v-tooltip top style="min-width: 150px"> <v-switch class="ml-3" slot="activator" :disabled="!darkModeUnlocked" v-model="darkMode" label="dark mode"/> <span v-if="darkModeUnlocked">Experimental: styling issues may occur!</span> <span v-else>You need to visit the feedback site below first!</span> </v-tooltip> <v-footer v-if="!mini" @click.native="logFeedbackClick"> <v-spacer/> <a href="https://gitlab.gwdg.de/j.michal/grady/issues" target="_blank" class="feedback-link" >Give us Feedback!</a> <v-spacer/> </v-footer> </div> </v-navigation-drawer> <v-toolbar app clipped-left fixed dark color="indigo darken-4" class="grady-toolbar" > <v-toolbar-title> <router-link to="/home"> <v-avatar> <img v-if="production" :src="productionBrandUrl"/> <img v-else src="../assets/brand.png"/> </v-avatar> </router-link> </v-toolbar-title> <span class="pl-2 grady-speak">{{ gradySpeak }}</span> <v-spacer/> <slot name="toolbar-center"/> <div class="toolbar-content"> <span>{{ userRole }} | {{ username }}</span> </div> <v-btn color="blue darken-1" to="/" @click.native="logout">Logout</v-btn> <slot name="toolbar-right"></slot> </v-toolbar> </div> </template> <script> import { mapGetters, mapState } from 'vuex' import {uiMut} from '@/store/modules/ui' import { createComputedGetterSetter } from '@/util/helpers' export default { name: 'base-layout', computed: { ...mapGetters([ 'gradySpeak' ]), ...mapState({ username: state => state.authentication.username, userRole: state => state.authentication.userRole }), darkMode: createComputedGetterSetter({ path: 'ui.darkMode', mutation: uiMut.SET_DARK_MODE }), darkModeUnlocked: createComputedGetterSetter({ path: 'ui.darkModeUnlocked', mutation: uiMut.SET_DARK_MODE_UNLOCKED }), mini: { get: function () { return this.$store.state.ui.sideBarCollapsed }, set: function (collapsed) { this.$store.commit(uiMut.SET_SIDEBAR_COLLAPSED, collapsed) } }, production () { return process.env.NODE_ENV === 'production' }, productionBrandUrl () { return `https://${window.location.host}/static/img/brand.png` } }, methods: { logout () { this.$store.dispatch('logout') }, logFeedbackClick () { this.darkModeUnlocked = true } } } </script> <style scoped> .sidebar-footer { position: absolute; width: 100%; bottom: 0px; } .feedback-link { text-decoration: none; color: grey; } .toolbar-content { margin-left: auto; } .grady-toolbar { font-weight: bold; } .title { color: gray; } </style>