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.

navigationItem.vue 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <!--
  2. - @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
  3. -
  4. - @author John Molakvoæ <skjnldsv@protonmail.com>
  5. -
  6. - @license GNU AGPL version 3 or any later version
  7. -
  8. - This program is free software: you can redistribute it and/or modify
  9. - it under the terms of the GNU Affero General Public License as
  10. - published by the Free Software Foundation, either version 3 of the
  11. - License, or (at your option) any later version.
  12. -
  13. - This program is distributed in the hope that it will be useful,
  14. - but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. - GNU Affero General Public License for more details.
  17. -
  18. - You should have received a copy of the GNU Affero General Public License
  19. - along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. -
  21. -->
  22. <template>
  23. <nav-element :id="item.id" v-bind="navElement(item)"
  24. :class="[{'icon-loading-small': item.loading, 'open': item.opened, 'collapsible': item.collapsible&&item.children&&item.children.length>0 }, item.classes]">
  25. <!-- Bullet -->
  26. <div v-if="item.bullet" class="app-navigation-entry-bullet" :style="{ backgroundColor: item.bullet }"></div>
  27. <!-- Main link -->
  28. <a :href="(item.href) ? item.href : '#' " @click="toggleCollapse" :class="item.icon">
  29. <img v-if="item.iconUrl" :alt="item.text" :src="item.iconUrl">
  30. {{item.text}}
  31. </a>
  32. <!-- Popover, counter and button(s) -->
  33. <div v-if="item.utils" class="app-navigation-entry-utils">
  34. <ul>
  35. <!-- counter -->
  36. <li v-if="Number.isInteger(item.utils.counter)"
  37. class="app-navigation-entry-utils-counter">{{item.utils.counter}}</li>
  38. <!-- first action if only one action and counter -->
  39. <li v-if="item.utils.actions && item.utils.actions.length === 1 && Number.isInteger(item.utils.counter)"
  40. class="app-navigation-entry-utils-menu-button">
  41. <button @click="item.utils.actions[0].action" :class="item.utils.actions[0].icon" :title="item.utils.actions[0].text"></button>
  42. </li>
  43. <!-- second action only two actions and no counter -->
  44. <li v-else-if="item.utils.actions && item.utils.actions.length === 2 && !Number.isInteger(item.utils.counter)"
  45. v-for="action in item.utils.actions" :key="action.action"
  46. class="app-navigation-entry-utils-menu-button">
  47. <button @click="action.action" :class="action.icon" :title="action.text"></button>
  48. </li>
  49. <!-- menu if only at least one action and counter OR two actions and no counter-->
  50. <li v-else-if="item.utils.actions && item.utils.actions.length > 1 && (Number.isInteger(item.utils.counter) || item.utils.actions.length > 2)"
  51. class="app-navigation-entry-utils-menu-button">
  52. <button v-click-outside="hideMenu" @click="showMenu" ></button>
  53. </li>
  54. </ul>
  55. </div>
  56. <!-- if more than 2 actions or more than 1 actions with counter -->
  57. <div v-if="item.utils && item.utils.actions && item.utils.actions.length > 1 && (Number.isInteger(item.utils.counter) || item.utils.actions.length > 2)"
  58. class="app-navigation-entry-menu" :class="{ 'open': openedMenu }">
  59. <popover-menu :menu="item.utils.actions"/>
  60. </div>
  61. <!-- undo entry -->
  62. <div class="app-navigation-entry-deleted" v-if="item.undo">
  63. <div class="app-navigation-entry-deleted-description">{{item.undo.text}}</div>
  64. <button class="app-navigation-entry-deleted-button icon-history" :title="t('settings', 'Undo')"></button>
  65. </div>
  66. <!-- edit entry -->
  67. <div class="app-navigation-entry-edit" v-if="item.edit">
  68. <form>
  69. <input type="text" v-model="item.text">
  70. <input type="submit" value="" class="icon-confirm">
  71. <input type="submit" value="" class="icon-close" @click.stop.prevent="cancelEdit">
  72. </form>
  73. </div>
  74. <!-- if the item has children, inject the component with proper data -->
  75. <ul v-if="item.children">
  76. <navigation-item v-for="(item, key) in item.children" :item="item" :key="key" />
  77. </ul>
  78. </nav-element>
  79. </template>
  80. <script>
  81. import popoverMenu from '../popoverMenu';
  82. import ClickOutside from 'vue-click-outside';
  83. import Vue from 'vue';
  84. export default {
  85. name: 'navigationItem',
  86. props: ['item'],
  87. components: {
  88. popoverMenu
  89. },
  90. directives: {
  91. ClickOutside
  92. },
  93. data() {
  94. return {
  95. openedMenu: false
  96. };
  97. },
  98. methods: {
  99. showMenu() {
  100. this.openedMenu = true;
  101. },
  102. hideMenu() {
  103. this.openedMenu = false;
  104. },
  105. toggleCollapse() {
  106. // if item.opened isn't set, Vue won't trigger view updates https://vuejs.org/v2/api/#Vue-set
  107. // ternary is here to detect the undefined state of item.opened
  108. Vue.set(this.item, 'opened', this.item.opened ? !this.item.opened : true);
  109. },
  110. cancelEdit() {
  111. // remove the editing class
  112. if (Array.isArray(this.item.classes))
  113. this.item.classes = this.item.classes.filter(
  114. item => item !== 'editing'
  115. );
  116. },
  117. // This is used to decide which outter element type to use
  118. // li or router-link
  119. navElement(item) {
  120. if (item.href) {
  121. return {
  122. is: 'li'
  123. };
  124. }
  125. return {
  126. is: 'router-link',
  127. tag: 'li',
  128. to: item.router,
  129. exact: true
  130. };
  131. }
  132. },
  133. mounted() {
  134. // prevent click outside event with popupItem.
  135. this.popupItem = this.$el;
  136. }
  137. };
  138. </script>