239 lines
7.4 KiB
Vue
239 lines
7.4 KiB
Vue
<template lang="pug">
|
|
div
|
|
.pa-3.d-flex(v-if='navMode === `MIXED`', :class='$vuetify.theme.dark ? `grey darken-5` : `blue darken-3`')
|
|
v-btn(
|
|
depressed
|
|
:color='$vuetify.theme.dark ? `grey darken-4` : `blue darken-2`'
|
|
style='min-width:0;'
|
|
@click='goHome'
|
|
:aria-label='$t(`common:header.home`)'
|
|
)
|
|
v-icon(size='20') mdi-home
|
|
v-btn.ml-3(
|
|
v-if='currentMode === `custom`'
|
|
depressed
|
|
:color='$vuetify.theme.dark ? `grey darken-4` : `blue darken-2`'
|
|
style='flex: 1 1 100%;'
|
|
@click='switchMode(`browse`)'
|
|
)
|
|
v-icon(left) mdi-file-tree
|
|
.body-2.text-none {{$t('common:sidebar.browse')}}
|
|
v-btn.ml-3(
|
|
v-else-if='currentMode === `browse`'
|
|
depressed
|
|
:color='$vuetify.theme.dark ? `grey darken-4` : `blue darken-2`'
|
|
style='flex: 1 1 100%;'
|
|
@click='switchMode(`custom`)'
|
|
)
|
|
v-icon(left) mdi-navigation
|
|
.body-2.text-none {{$t('common:sidebar.mainMenu')}}
|
|
v-divider
|
|
//-> Custom Navigation
|
|
v-list.py-2(v-if='currentMode === `custom`', dense, :class='color', :dark='dark')
|
|
template(v-for='item of items')
|
|
v-list-item(
|
|
v-if='item.k === `link`'
|
|
:href='item.t'
|
|
:target='item.y === `externalblank` ? `_blank` : `_self`'
|
|
:rel='item.y === `externalblank` ? `noopener` : ``'
|
|
)
|
|
v-list-item-avatar(size='24', tile)
|
|
v-icon(v-if='item.c.match(/fa[a-z] fa-/)', size='19') {{ item.c }}
|
|
v-icon(v-else) {{ item.c }}
|
|
v-list-item-title {{ item.l }}
|
|
v-divider.my-2(v-else-if='item.k === `divider`')
|
|
v-subheader.pl-4(v-else-if='item.k === `header`') {{ item.l }}
|
|
//-> Browse
|
|
v-list.py-2(v-else-if='currentMode === `browse`', dense, :class='color', :dark='dark')
|
|
template(v-if='currentParent.id > 0')
|
|
v-list-item(v-for='(item, idx) of parents', :key='`parent-` + item.id', @click='fetchBrowseItems(item)', style='min-height: 30px;')
|
|
v-list-item-avatar(size='18', :style='`padding-left: ` + (idx * 8) + `px; width: auto; margin: 0 5px 0 0;`')
|
|
v-icon(small) mdi-folder-open
|
|
v-list-item-title {{ item.title }}
|
|
v-divider.mt-2
|
|
v-list-item.mt-2(v-if='currentParent.pageId > 0', :href='`/` + currentParent.locale + `/` + currentParent.path', :key='`directorypage-` + currentParent.id', :input-value='path === currentParent.path')
|
|
v-list-item-avatar(size='24')
|
|
v-icon mdi-text-box
|
|
v-list-item-title {{ currentParent.title }}
|
|
v-subheader.pl-4 {{$t('common:sidebar.currentDirectory')}}
|
|
template(v-for='item of currentItems')
|
|
v-list-item(v-if='item.isFolder', :key='`childfolder-` + item.id', @click='fetchBrowseItems(item)')
|
|
v-list-item-avatar(size='24')
|
|
v-icon mdi-folder
|
|
v-list-item-title {{ item.title }}
|
|
v-list-item(v-else, :href='`/` + item.locale + `/` + item.path', :key='`childpage-` + item.id', :input-value='path === item.path')
|
|
v-list-item-avatar(size='24')
|
|
v-icon mdi-text-box
|
|
v-list-item-title {{ item.title }}
|
|
</template>
|
|
|
|
<script>
|
|
import _ from 'lodash'
|
|
import gql from 'graphql-tag'
|
|
import { get } from 'vuex-pathify'
|
|
|
|
/* global siteLangs */
|
|
|
|
export default {
|
|
props: {
|
|
color: {
|
|
type: String,
|
|
default: 'primary'
|
|
},
|
|
dark: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
items: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
navMode: {
|
|
type: String,
|
|
default: 'MIXED'
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
currentMode: 'custom',
|
|
currentItems: [],
|
|
currentParent: {
|
|
id: 0,
|
|
title: '/ (root)'
|
|
},
|
|
parents: [],
|
|
loadedCache: []
|
|
}
|
|
},
|
|
computed: {
|
|
path: get('page/path'),
|
|
locale: get('page/locale')
|
|
},
|
|
methods: {
|
|
switchMode (mode) {
|
|
this.currentMode = mode
|
|
window.localStorage.setItem('navPref', mode)
|
|
if (mode === `browse` && this.loadedCache.length < 1) {
|
|
this.loadFromCurrentPath()
|
|
}
|
|
},
|
|
async fetchBrowseItems (item) {
|
|
this.$store.commit(`loadingStart`, 'browse-load')
|
|
if (!item) {
|
|
item = this.currentParent
|
|
}
|
|
|
|
if (this.loadedCache.indexOf(item.id) < 0) {
|
|
this.currentItems = []
|
|
}
|
|
|
|
if (item.id === 0) {
|
|
this.parents = []
|
|
} else {
|
|
const flushRightIndex = _.findIndex(this.parents, ['id', item.id])
|
|
if (flushRightIndex >= 0) {
|
|
this.parents = _.take(this.parents, flushRightIndex)
|
|
}
|
|
if (this.parents.length < 1) {
|
|
this.parents.push(this.currentParent)
|
|
}
|
|
this.parents.push(item)
|
|
}
|
|
|
|
this.currentParent = item
|
|
|
|
const resp = await this.$apollo.query({
|
|
query: gql`
|
|
query ($parent: Int, $locale: String!) {
|
|
pages {
|
|
tree(parent: $parent, mode: ALL, locale: $locale) {
|
|
id
|
|
path
|
|
title
|
|
isFolder
|
|
pageId
|
|
parent
|
|
locale
|
|
}
|
|
}
|
|
}
|
|
`,
|
|
fetchPolicy: 'cache-first',
|
|
variables: {
|
|
parent: item.id,
|
|
locale: this.locale
|
|
}
|
|
})
|
|
this.loadedCache = _.union(this.loadedCache, [item.id])
|
|
this.currentItems = _.get(resp, 'data.pages.tree', [])
|
|
this.$store.commit(`loadingStop`, 'browse-load')
|
|
},
|
|
async loadFromCurrentPath() {
|
|
this.$store.commit(`loadingStart`, 'browse-load')
|
|
const resp = await this.$apollo.query({
|
|
query: gql`
|
|
query ($path: String, $locale: String!) {
|
|
pages {
|
|
tree(path: $path, mode: ALL, locale: $locale, includeAncestors: true) {
|
|
id
|
|
path
|
|
title
|
|
isFolder
|
|
pageId
|
|
parent
|
|
locale
|
|
}
|
|
}
|
|
}
|
|
`,
|
|
fetchPolicy: 'cache-first',
|
|
variables: {
|
|
path: this.path,
|
|
locale: this.locale
|
|
}
|
|
})
|
|
const items = _.get(resp, 'data.pages.tree', [])
|
|
const curPage = _.find(items, ['pageId', this.$store.get('page/id')])
|
|
if (!curPage) {
|
|
console.warn('Could not find current page in page tree listing!')
|
|
return
|
|
}
|
|
|
|
let curParentId = curPage.parent
|
|
let invertedAncestors = []
|
|
while (curParentId) {
|
|
const curParent = _.find(items, ['id', curParentId])
|
|
if (!curParent) {
|
|
break
|
|
}
|
|
invertedAncestors.push(curParent)
|
|
curParentId = curParent.parent
|
|
}
|
|
|
|
this.parents = [this.currentParent, ...invertedAncestors.reverse()]
|
|
this.currentParent = _.last(this.parents)
|
|
|
|
this.loadedCache = [curPage.parent]
|
|
this.currentItems = _.filter(items, ['parent', curPage.parent])
|
|
this.$store.commit(`loadingStop`, 'browse-load')
|
|
},
|
|
goHome () {
|
|
window.location.assign(siteLangs.length > 0 ? `/${this.locale}/home` : '/')
|
|
}
|
|
},
|
|
mounted () {
|
|
this.currentParent.title = `/ ${this.$t('common:sidebar.root')}`
|
|
if (this.navMode === 'TREE') {
|
|
this.currentMode = 'browse'
|
|
} else if (this.navMode === 'STATIC') {
|
|
this.currentMode = 'custom'
|
|
} else {
|
|
this.currentMode = window.localStorage.getItem('navPref') || 'custom'
|
|
}
|
|
if (this.currentMode === 'browse') {
|
|
this.loadFromCurrentPath()
|
|
}
|
|
}
|
|
}
|
|
</script>
|