SolidScribe/client/src/components/GlobalSiteMenu.vue

459 lines
12 KiB
Vue
Raw Normal View History

<style scoped>
.slotholder {
height: 100vh;
width: 155px;
display: block;
float: left;
}
.global-menu {
width: 155px;
background: #221f2b;
margin: 0;
padding: 0;
box-sizing: border-box;
display: block;
position: fixed;
z-index: 111;
top: 0;
left: 0;
bottom: 0;
}
.menu-logo-display {
width: 27px;
margin: 5px 0 0 41px;
display: inline-block;
height: auto;
}
.menu-item {
color: #fff;
padding: 9px 10px;
display: inline-block;
width: 100%;
font-size: 1.1em;
box-sizing: border-box;
}
2020-02-01 14:21:22 -08:00
.menu-item i.icon {
margin-right: 10px;
}
.sub {
padding-left: 20px;
}
.menu-section {}
.menu-section + .menu-section {
border-top: 1px solid #534c68;
}
.menu-button {
cursor: pointer;
}
.menu-button:hover {
background-color: #534c68;
2020-02-01 14:21:22 -08:00
text-decoration: none;
}
.router-link-active i {
/*color: #16ab39;*/
}
.router-link-active {
background-color: #534c68;
}
.shade {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.7);
z-index: 100;
cursor: pointer;
}
.top-menu-bar {
/*color: var(--text_color);*/
/*width: 100%;*/
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
background-color: var(--small_element_bg_color);
border-bottom: 1px solid;
border-color: var(--border_color);
/*padding: 5px 1rem 5px;*/
display: flex;
justify-content: space-around;
}
.place-holder {
width: 100%;
height: 50px;
}
.logo-display {
width: 27px;
height: auto;
}
.version-display {
position: absolute;
bottom: 0;
left: -20px;
right: 0;
height: 30px;
padding: 5px 0;
text-align: center;
color: #8c80ae;
cursor: pointer;
}
.mobile-button {
display: inline-block;
font-size: 2em;
padding: 6px 3px 5px;
cursor: pointer;
}
.mobile-button.active {
background-color: transparent;
}
.mobile-button i {
margin: 0;
}
</style>
<template>
<div>
<div class="place-holder" v-if="collapsed && !menuOpen"></div>
<!-- collapsed menu, appears as a bar -->
<div class="top-menu-bar" v-if="(collapsed || mobile) && !menuOpen">
<div class="mobile-button">
<i class="green link bars icon" v-on:click="collapseMenu"></i>
</div>
2020-02-01 14:21:22 -08:00
<div class="mobile-button"></div>
2020-02-01 14:21:22 -08:00
<!-- open straight to note -->
<router-link
v-if="loggedIn && $store.getters.totals && $store.getters.totals['quickNote']"
exact-active-class="active"
class="mobile-button"
:to="`/notes/open/${$store.getters.totals['quickNote']}`">
<i class="green sticky note outline icon"></i>
</router-link>
<!-- create new and redirect to new note id -->
<a
v-if="loggedIn && $store.getters.totals && !$store.getters.totals['quickNote']"
v-on:click="newQuickNote()"
exact-active-class="active"
class="mobile-button">
<i class="green sticky note outline icon"></i>
</a>
<router-link v-if="loggedIn" class="mobile-button" exact-active-class="active" to="/notes" v-on:click.native="emitReloadEvent()">
<logo class="logo-display" color="var(--main-accent)" />
</router-link>
<router-link v-if="loggedIn" class="mobile-button" exact-active-class="active" to="/attachments">
<i class="green open folder outline icon"></i>
</router-link>
<div class="mobile-button"></div>
<!-- mobile create note button -->
<span v-if="loggedIn">
<span v-if="!disableNewNote" @click="createNote" class="mobile-button">
<i class="green plus icon"></i>
</span>
<span v-if="disableNewNote" class="mobile-button">
<i class="grey plus icon"></i>
</span>
</span>
</div>
<div class="shade" v-if="mobile && !collapsed" v-on:click="collapseMenu"></div>
<div class="slotholder" v-if="!collapsed && !mobile">
</div>
<div class="global-menu" v-if="!collapsed" v-on:click="menuClicked">
<div class="menu-section" v-on:click="collapseMenu">
<i class="white angle left icon"></i>
<logo class="menu-logo-display" color="var(--main-accent)" />
</div>
<div class="menu-section" v-if="loggedIn">
<div v-if="!disableNewNote" @click="createNote" class="menu-item menu-item menu-button">
<div class="ui green button">
<i class="plus icon"></i>New Note
</div>
</div>
<div v-if="disableNewNote" class="menu-item menu-item menu-button">
<div class="ui basic button">
<i class="plus loading icon"></i>New Note
</div>
</div>
</div>
<div class="menu-section" v-if="loggedIn">
<router-link exact-active-class="active" class="menu-item menu-button" to="/notes" v-on:click.native="emitReloadEvent()">
<i class="file outline icon"></i>Notes
<counter v-if="$store.getters.totals && $store.getters.totals['totalNotes']" class="float-right" number-id="totalNotes" />
</router-link>
<div>
<div class="menu-item menu-button sub" v-on:click="updateFastFilters(3)" v-if="$store.getters.totals && ($store.getters.totals['sharedToNotes'] > 0 || $store.getters.totals['sharedFromNotes'] > 0)">
<i class="grey mail outline icon"></i>Inbox
</div>
<div class="menu-item menu-button sub" v-on:click="updateFastFilters(2)" v-if="$store.getters.totals && $store.getters.totals['archivedNotes'] > 0">
<i class="grey archive icon"></i>Archived
<!-- <span>{{ $store.getters.totals['archivedNotes'] }}</span> -->
</div>
<div class="menu-item menu-button sub" v-on:click="updateFastFilters(4)" v-if="$store.getters.totals && $store.getters.totals['trashedNotes'] > 0">
<i class="grey trash alternate outline icon"></i>Trashed
</div>
2020-02-01 14:21:22 -08:00
<!-- <div class="menu-item sub">Show Only <i class="caret down icon"></i></div> -->
<!-- <div v-on:click="updateFastFilters(0)" class="menu-item menu-button sub"><i class="grey linkify icon"></i>Links</div> -->
<!-- <div v-on:click="updateFastFilters(1)" class="menu-item menu-button sub"><i class="grey tags icon"></i>Tags</div> -->
</div>
</div>
<div class="menu-section" v-if="loggedIn && $store.getters.totals && $store.getters.totals['totalFiles']">
<router-link class="menu-item menu-button" exact-active-class="active" to="/attachments">
<i class="open folder outline icon"></i>Files
<counter class="float-right" number-id="totalFiles" />
</router-link>
</div>
<div class="menu-section" v-if="loggedIn">
<!-- open straight to note -->
<router-link
v-if="loggedIn && $store.getters.totals && $store.getters.totals['quickNote']"
exact-active-class="active"
class="menu-item menu-button"
:to="`/notes/open/${$store.getters.totals['quickNote']}`">
<i class="sticky note outline icon"></i>Scratch Pad
</router-link>
<!-- create new and redirect to new note id -->
<a
v-if="loggedIn && $store.getters.totals && !$store.getters.totals['quickNote']"
v-on:click="newQuickNote()"
exact-active-class="active"
class="menu-item menu-button">
<i class="sticky note outline icon"></i>Scratch Pad
</a>
</div>
<div class="menu-section" v-if="!loggedIn">
<router-link v-if="!loggedIn" class="menu-item menu-button" exact-active-class="active" to="/">
<i class="home icon"></i>Welcome
</router-link>
<router-link exact-active-class="active" class="menu-item menu-button" to="/login">
<i class="plug icon"></i>Login
</router-link>
</div>
<div class="menu-section">
<div v-on:click="toggleNightMode" class="menu-item menu-button">
<span v-if="$store.getters.getIsNightMode == 0">
<i class="moon outline icon"></i>Black Theme</span>
<span v-if="$store.getters.getIsNightMode == 1">
<i class="moon outline icon"></i>Flux Theme</span>
<span v-if="$store.getters.getIsNightMode == 2">
2020-02-01 14:21:22 -08:00
<i class="moon outline icon"></i>Light Theme</span>
</div>
</div>
<div class="menu-section">
<router-link class="menu-item menu-button" exact-active-class="active" to="/help">
<i class="question circle outline icon"></i>Help | Terms
</router-link>
</div>
<div class="menu-section" v-if="loggedIn" :data-tooltip="`Settings for ${this.$store.getters.getUsername}`" data-inverted="" data-position="right center">
<router-link class="menu-item menu-button" exact-active-class="active" to="/settings">
<i v-if="userIcon" class="cog icon"></i>{{ usernameDisplay }}
</router-link>
</div>
<div v-on:click="reloadPage" class="version-display" v-if="version != 0" >
<i :class="`${getVersionIcon()} icon`"></i> {{ version }}
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
components: {
'search-input': require('@/components/SearchInput.vue').default,
'counter':require('@/components/AnimatedCounterComponent.vue').default,
'logo':require('@/components/LogoComponent.vue').default,
},
data: function(){
return {
version: '0',
username: '',
collapsed: false,
mobile: false,
disableNewNote: false,
menuOpen: true,
userIcon: true,
resizeDebounce: null,
}
},
beforeMount(){
window.addEventListener('resize', this.resizeEventHandler)
},
beforeDestroy(){
window.removeEventListener('resize', this.resizeEventHandler)
},
mounted: function(){
this.mobile = this.$store.getters.getIsUserOnMobile
this.collapsed = this.$store.getters.getIsUserOnMobile
if(this.mobile){
this.menuOpen = false
}
if(this.loggedIn){
this.$store.dispatch('fetchAndUpdateUserTotals')
this.version = localStorage.getItem('currentVersion')
}
this.resizeEventHandler() //Trigger resize event
},
computed: {
loggedIn () {
//Map logged in from state
return this.$store.getters.getLoggedIn
},
usernameDisplay() {
//Remove Emails from username, limit length to 16 chars
let name = this.$store.getters.getUsername
let splitName = name.split('@')
if(splitName.length > 1){
name = splitName.shift()
this.userIcon = false
}
if(name.length > 16){
this.userIcon = false
}
return this.ucWords(name.substring(0, 16))
},
},
methods: {
newQuickNote(){
axios.post('/api/quick-note/get')
.then( ({data}) => {
console.log(data)
this.$router.push({'path':'/notes/open/'+data.noteId})
})
},
resizeEventHandler(e) {
clearTimeout(this.resizeDebounce)
this.resizeDebounce = setTimeout(() => {
this.mobile = false
this.menuOpen = false
this.collapsed = false
if(window.innerWidth < 700){
this.collapsed = true
this.mobile = true
}
}, 100)
},
menuClicked(){
//Collapse menu when item is clicked in mobile
if(this.mobile && !this.collapsed){
this.collapsed = true
this.menuOpen = false
}
},
collapseMenu(){
this.collapsed = !this.collapsed
if(!this.collapsed){
this.menuOpen = true
} else {
this.menuOpen = false
}
},
createNote(event){
this.disableNewNote = true
axios.post('/api/note/create', {title:''})
.then(response => {
if(response.data && response.data.id){
//Push new note to url and it will open
this.$router.push('/notes/open/'+response.data.id)
this.disableNewNote = false
}
})
.catch(error => { this.$bus.$emit('notification', 'Failed to create note') })
},
toggleNightMode(){
this.$store.commit('toggleNightMode')
},
ucWords(str){
return (str + '')
.replace(/^(.)|\s+(.)/g, function ($1) {
return $1.toUpperCase()
})
},
emitReloadEvent(){
//Reloads note page to initial state
this.$bus.$emit('note_reload')
},
updateFastFilters(filterIndex){
//A little hacky, brings user to notes page then filters on click
if(this.$route.name != 'Note Page'){
this.$router.push('/notes')
setTimeout( () => {
this.$bus.$emit('update_fast_filters', filterIndex)
}, 500 )
} else {
this.$bus.$emit('update_fast_filters', filterIndex)
}
},
reloadPage(){
location.reload(true)
},
getVersionIcon(){
const icons = ['cat','crow','dog','dove','dragon','fish','frog','hippo','horse','kiwi bird','otter','spider', 'smile', 'robot', 'hat wizard', 'microchip', 'atom', 'grin tongue squint', 'radiation', 'ghost', 'dna', 'burn', 'brain', 'moon', 'torii gate']
const index = ( parseInt(this.version.replace(/\./g,'')) % (icons.length))
return icons[index]
}
}
}
</script>