You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
6.4 KiB

  1. <template lang="pug">
  2. div
  3. .blue.darken-3.pa-3.d-flex(v-if='navMode === `MIXED`')
  4. v-btn(depressed, color='blue darken-2', style='min-width:0;', @click='goHome')
  5. v-icon(size='20') mdi-home
  6. v-btn.ml-3(v-if='currentMode === `custom`', depressed, color='blue darken-2', style='flex: 1 1 100%;', @click='switchMode(`browse`)')
  7. v-icon(left) mdi-file-tree
  8. .body-2.text-none {{$t('common:sidebar.browse')}}
  9. v-btn.ml-3(v-else-if='currentMode === `browse`', depressed, color='blue darken-2', style='flex: 1 1 100%;', @click='switchMode(`custom`)')
  10. v-icon(left) mdi-navigation
  11. .body-2.text-none {{$t('common:sidebar.mainMenu')}}
  12. v-divider
  13. //-> Custom Navigation
  14. v-list.py-2(v-if='currentMode === `custom`', dense, :class='color', :dark='dark')
  15. template(v-for='item of items')
  16. v-list-item(
  17. v-if='item.kind === `link`'
  18. :href='item.target'
  19. )
  20. v-list-item-avatar(size='24', tile)
  21. v-icon {{ item.icon }}
  22. v-list-item-title {{ item.label }}
  23. v-divider.my-2(v-else-if='item.kind === `divider`')
  24. v-subheader.pl-4(v-else-if='item.kind === `header`') {{ item.label }}
  25. //-> Browse
  26. v-list.py-2(v-else-if='currentMode === `browse`', dense, :class='color', :dark='dark')
  27. template(v-if='currentParent.id > 0')
  28. v-list-item(v-for='(item, idx) of parents', :key='`parent-` + item.id', @click='fetchBrowseItems(item)', style='min-height: 30px;')
  29. v-list-item-avatar(size='18', :style='`padding-left: ` + (idx * 8) + `px; width: auto; margin: 0 5px 0 0;`')
  30. v-icon(small) mdi-folder-open
  31. v-list-item-title {{ item.title }}
  32. v-divider.mt-2
  33. v-subheader.pl-4 {{$t('common:sidebar.currentDirectory')}}
  34. template(v-for='item of currentItems')
  35. v-list-item(v-if='item.isFolder', :key='`childfolder-` + item.id', @click='fetchBrowseItems(item)')
  36. v-list-item-avatar(size='24')
  37. v-icon mdi-folder
  38. v-list-item-title {{ item.title }}
  39. v-list-item(v-else, :href='`/` + item.path', :key='`childpage-` + item.id', :input-value='path === item.path')
  40. v-list-item-avatar(size='24')
  41. v-icon mdi-text-box
  42. v-list-item-title {{ item.title }}
  43. </template>
  44. <script>
  45. import _ from 'lodash'
  46. import gql from 'graphql-tag'
  47. import { get } from 'vuex-pathify'
  48. /* global siteLangs */
  49. export default {
  50. props: {
  51. color: {
  52. type: String,
  53. default: 'primary'
  54. },
  55. dark: {
  56. type: Boolean,
  57. default: true
  58. },
  59. items: {
  60. type: Array,
  61. default: () => []
  62. },
  63. navMode: {
  64. type: String,
  65. default: 'MIXED'
  66. }
  67. },
  68. data() {
  69. return {
  70. currentMode: 'custom',
  71. currentItems: [],
  72. currentParent: {
  73. id: 0,
  74. title: '/ (root)'
  75. },
  76. parents: [],
  77. loadedCache: []
  78. }
  79. },
  80. computed: {
  81. path: get('page/path'),
  82. locale: get('page/locale')
  83. },
  84. methods: {
  85. switchMode (mode) {
  86. this.currentMode = mode
  87. window.localStorage.setItem('navPref', mode)
  88. if (mode === `browse` && this.loadedCache.length < 1) {
  89. this.loadFromCurrentPath()
  90. }
  91. },
  92. async fetchBrowseItems (item) {
  93. this.$store.commit(`loadingStart`, 'browse-load')
  94. if (!item) {
  95. item = this.currentParent
  96. }
  97. if (this.loadedCache.indexOf(item.id) < 0) {
  98. this.currentItems = []
  99. }
  100. if (item.id === 0) {
  101. this.parents = []
  102. } else {
  103. const flushRightIndex = _.findIndex(this.parents, ['id', item.id])
  104. if (flushRightIndex >= 0) {
  105. this.parents = _.take(this.parents, flushRightIndex)
  106. }
  107. if (this.parents.length < 1) {
  108. this.parents.push(this.currentParent)
  109. }
  110. this.parents.push(item)
  111. }
  112. this.currentParent = item
  113. const resp = await this.$apollo.query({
  114. query: gql`
  115. query ($parent: Int, $locale: String!) {
  116. pages {
  117. tree(parent: $parent, mode: ALL, locale: $locale) {
  118. id
  119. path
  120. title
  121. isFolder
  122. pageId
  123. parent
  124. }
  125. }
  126. }
  127. `,
  128. fetchPolicy: 'cache-first',
  129. variables: {
  130. parent: item.id,
  131. locale: this.locale
  132. }
  133. })
  134. this.loadedCache = _.union(this.loadedCache, [item.id])
  135. this.currentItems = _.get(resp, 'data.pages.tree', [])
  136. this.$store.commit(`loadingStop`, 'browse-load')
  137. },
  138. async loadFromCurrentPath() {
  139. this.$store.commit(`loadingStart`, 'browse-load')
  140. const resp = await this.$apollo.query({
  141. query: gql`
  142. query ($path: String, $locale: String!) {
  143. pages {
  144. tree(path: $path, mode: ALL, locale: $locale, includeAncestors: true) {
  145. id
  146. path
  147. title
  148. isFolder
  149. pageId
  150. parent
  151. }
  152. }
  153. }
  154. `,
  155. fetchPolicy: 'cache-first',
  156. variables: {
  157. path: this.path,
  158. locale: this.locale
  159. }
  160. })
  161. const items = _.get(resp, 'data.pages.tree', [])
  162. const curPage = _.find(items, ['pageId', this.$store.get('page/id')])
  163. if (!curPage) {
  164. console.warn('Could not find current page in page tree listing!')
  165. return
  166. }
  167. let curParentId = curPage.parent
  168. let invertedAncestors = []
  169. while (curParentId) {
  170. const curParent = _.find(items, ['id', curParentId])
  171. if (!curParent) {
  172. break
  173. }
  174. invertedAncestors.push(curParent)
  175. curParentId = curParent.parent
  176. }
  177. this.parents = [this.currentParent, ...invertedAncestors.reverse()]
  178. this.currentParent = _.last(this.parents)
  179. this.loadedCache = [curPage.parent]
  180. this.currentItems = _.filter(items, ['parent', curPage.parent])
  181. this.$store.commit(`loadingStop`, 'browse-load')
  182. },
  183. goHome () {
  184. window.location.assign(siteLangs.length > 0 ? `/${this.locale}/home` : '/')
  185. }
  186. },
  187. mounted () {
  188. this.currentParent.title = `/ ${this.$t('common:sidebar.root')}`
  189. if (this.navMode === 'TREE') {
  190. this.currentMode = 'browse'
  191. } else {
  192. this.currentMode = window.localStorage.getItem('navPref') || 'custom'
  193. }
  194. if (this.currentMode === 'browse') {
  195. this.loadFromCurrentPath()
  196. }
  197. }
  198. }
  199. </script>