2
0

admin-navigation.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <template lang='pug'>
  2. v-container(fluid, fill-height)
  3. v-layout(row wrap)
  4. v-flex(xs12)
  5. .admin-header-icon: v-icon(size='80', color='grey lighten-2') near_me
  6. .headline.primary--text {{$t('navigation.title')}}
  7. .subheading.grey--text {{$t('navigation.subtitle')}}
  8. v-container.pa-0.mt-3(fluid, grid-list-lg)
  9. v-layout(row)
  10. v-flex(style='flex: 0 0 350px;')
  11. v-card
  12. v-list.primary.py-2(dense, dark)
  13. draggable(v-model='navTree')
  14. template(v-for='navItem in navTree')
  15. v-list-tile(
  16. v-if='navItem.kind === "link"'
  17. :key='navItem.id'
  18. :class='(navItem === current) ? "blue" : ""'
  19. @click='selectItem(navItem)'
  20. )
  21. v-list-tile-avatar: v-icon {{navItem.icon}}
  22. v-list-tile-title {{navItem.label}}
  23. .py-2.clickable(
  24. v-else-if='navItem.kind === "divider"'
  25. :key='navItem.id'
  26. :class='(navItem === current) ? "blue" : ""'
  27. @click='selectItem(navItem)'
  28. )
  29. v-divider
  30. v-subheader.pl-4.clickable(
  31. v-else-if='navItem.kind === "header"'
  32. :key='navItem.id'
  33. :class='(navItem === current) ? "blue" : ""'
  34. @click='selectItem(navItem)'
  35. ) {{navItem.label}}
  36. v-card-chin
  37. v-menu(offset-y, bottom, min-width='200px', style='flex: 1 1;')
  38. v-btn(slot='activator', color='primary', depressed, block)
  39. v-icon(left) add
  40. span {{$t('common:actions.add')}}
  41. v-list
  42. v-list-tile(@click='addItem("link")')
  43. v-list-tile-avatar: v-icon link
  44. v-list-tile-title {{$t('navigation.link')}}
  45. v-list-tile(@click='addItem("header")')
  46. v-list-tile-avatar: v-icon title
  47. v-list-tile-title {{$t('navigation.header')}}
  48. v-list-tile(@click='addItem("divider")')
  49. v-list-tile-avatar: v-icon power_input
  50. v-list-tile-title {{$t('navigation.divider')}}
  51. v-btn.ml-2(color='success', depressed, block, @click='save')
  52. v-icon(left) check
  53. span {{$t('common:actions.save')}}
  54. v-flex
  55. v-card(v-if='current.kind === "link"')
  56. v-toolbar(dense, color='blue', flat, dark)
  57. .subheading {{$t('navigation.edit', { kind: $t('navigation.link') })}}
  58. v-card-text
  59. v-text-field(
  60. outline
  61. background-color='grey lighten-2'
  62. :label='$t("navigation.label")'
  63. prepend-icon='title'
  64. v-model='current.label'
  65. )
  66. v-text-field(
  67. outline
  68. background-color='grey lighten-2'
  69. :label='$t("navigation.icon")'
  70. prepend-icon='casino'
  71. v-model='current.icon'
  72. )
  73. v-select(
  74. outline
  75. background-color='grey lighten-2'
  76. :label='$t("navigation.targetType")'
  77. prepend-icon='near_me'
  78. :items='navTypes'
  79. v-model='current.targetType'
  80. )
  81. v-text-field(
  82. v-if='current.targetType === "external"'
  83. outline
  84. background-color='grey lighten-2'
  85. :label='$t("navigation.target")'
  86. prepend-icon='near_me'
  87. v-model='current.target'
  88. )
  89. v-card-chin
  90. v-spacer
  91. v-btn(color='red', outline, @click='deleteItem(current)')
  92. v-icon(left) delete
  93. span {{$t('navigation.delete', { kind: $t('navigation.link') })}}
  94. v-card(v-else-if='current.kind === "header"')
  95. v-toolbar(dense, color='blue', flat, dark)
  96. .subheading {{$t('navigation.edit', { kind: $t('navigation.header') })}}
  97. v-card-text
  98. v-text-field(
  99. outline
  100. background-color='grey lighten-2'
  101. :label='$t("navigation.label")'
  102. prepend-icon='title'
  103. v-model='current.label'
  104. )
  105. v-card-chin
  106. v-spacer
  107. v-btn(color='red', outline, @click='deleteItem(current)')
  108. v-icon(left) delete
  109. span {{$t('navigation.delete', { kind: $t('navigation.header') })}}
  110. div(v-else-if='current.kind === "divider"')
  111. v-btn.mt-0(color='red', outline, @click='deleteItem(current)')
  112. v-icon(left) delete
  113. span {{$t('navigation.delete', { kind: $t('navigation.divider') })}}
  114. v-card(v-else)
  115. v-card-text.grey--text {{$t('navigation.noSelectionText')}}
  116. </template>
  117. <script>
  118. import _ from 'lodash'
  119. import uuid from 'uuid/v4'
  120. import treeSaveMutation from 'gql/admin/navigation/navigation-mutation-save-tree.gql'
  121. import treeQuery from 'gql/admin/navigation/navigation-query-tree.gql'
  122. import draggable from 'vuedraggable'
  123. export default {
  124. components: {
  125. draggable
  126. },
  127. data() {
  128. return {
  129. navTree: [],
  130. current: {}
  131. }
  132. },
  133. computed: {
  134. navTypes() {
  135. return [
  136. { text: this.$t('navigation.navType.external'), value: 'external' },
  137. { text: this.$t('navigation.navType.home'), value: 'home' },
  138. { text: this.$t('navigation.navType.page'), value: 'page' },
  139. { text: this.$t('navigation.navType.searchQuery'), value: 'search' }
  140. ]
  141. }
  142. },
  143. methods: {
  144. addItem(kind) {
  145. let newItem = {
  146. id: uuid(),
  147. kind
  148. }
  149. switch (kind) {
  150. case 'link':
  151. newItem = {
  152. ...newItem,
  153. label: this.$t('navigation.untitled', { kind: this.$t(`navigation.link`) }),
  154. icon: 'chevron_right',
  155. targetType: 'home',
  156. target: '/'
  157. }
  158. break
  159. case 'header':
  160. newItem.label = this.$t('navigation.untitled', { kind: this.$t(`navigation.header`) })
  161. break
  162. }
  163. this.navTree.push(newItem)
  164. this.current = newItem
  165. },
  166. deleteItem(item) {
  167. this.navTree = _.pull(this.navTree, item)
  168. this.current = {}
  169. },
  170. selectItem(item) {
  171. this.current = item
  172. },
  173. async save() {
  174. this.$store.commit(`loadingStart`, 'admin-navigation-save')
  175. try {
  176. await this.$apollo.mutate({
  177. mutation: treeSaveMutation,
  178. variables: {
  179. tree: this.navTree
  180. }
  181. })
  182. } catch (err) {
  183. this.$store.commit('showNotification', {
  184. message: this.$t('navigation.saveSuccess'),
  185. style: 'success',
  186. icon: 'check'
  187. })
  188. }
  189. this.$store.commit(`loadingStop`, 'admin-navigation-save')
  190. }
  191. },
  192. apollo: {
  193. navTree: {
  194. query: treeQuery,
  195. fetchPolicy: 'network-only',
  196. update: (data) => _.cloneDeep(data.navigation.tree),
  197. watchLoading (isLoading) {
  198. this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-navigation-tree')
  199. }
  200. }
  201. }
  202. }
  203. </script>
  204. <style lang='scss' scoped>
  205. .clickable {
  206. cursor: pointer;
  207. &:hover {
  208. background-color: rgba(mc('blue', '500'), .25);
  209. }
  210. }
  211. </style>