Folder.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <template>
  2. <div class="flex flex-col">
  3. <div class="group flex items-center">
  4. <span
  5. class="flex items-center justify-center px-4 cursor-pointer"
  6. @click="toggleShowChildren()"
  7. >
  8. <SmartIcon
  9. class="svg-icons"
  10. :class="{ 'text-green-500': isSelected }"
  11. :name="getCollectionIcon"
  12. />
  13. </span>
  14. <span
  15. class="group-hover:text-secondaryDark flex flex-1 min-w-0 py-2 pr-2 transition cursor-pointer"
  16. @click="toggleShowChildren()"
  17. >
  18. <span class="truncate">
  19. {{ folder.name ? folder.name : folder.title }}
  20. </span>
  21. </span>
  22. <div class="flex">
  23. <ButtonSecondary
  24. v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
  25. v-tippy="{ theme: 'tooltip' }"
  26. svg="folder-plus"
  27. :title="$t('folder.new')"
  28. class="group-hover:inline-flex hidden"
  29. @click.native="$emit('add-folder', { folder, path: folderPath })"
  30. />
  31. <span>
  32. <tippy
  33. v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
  34. ref="options"
  35. interactive
  36. trigger="click"
  37. theme="popover"
  38. arrow
  39. >
  40. <template #trigger>
  41. <ButtonSecondary
  42. v-tippy="{ theme: 'tooltip' }"
  43. :title="$t('action.more')"
  44. svg="more-vertical"
  45. />
  46. </template>
  47. <SmartItem
  48. v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
  49. svg="folder-plus"
  50. :label="$t('folder.new')"
  51. @click.native="
  52. () => {
  53. $emit('add-folder', { folder, path: folderPath })
  54. $refs.options.tippy().hide()
  55. }
  56. "
  57. />
  58. <SmartItem
  59. v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
  60. svg="edit"
  61. :label="$t('action.edit')"
  62. @click.native="
  63. () => {
  64. $emit('edit-folder', {
  65. folder,
  66. folderIndex,
  67. collectionIndex,
  68. folderPath: '',
  69. })
  70. $refs.options.tippy().hide()
  71. }
  72. "
  73. />
  74. <SmartItem
  75. v-if="collectionsType.selectedTeam.myRole !== 'VIEWER'"
  76. svg="trash-2"
  77. color="red"
  78. :label="$t('action.delete')"
  79. @click.native="
  80. () => {
  81. confirmRemove = true
  82. $refs.options.tippy().hide()
  83. }
  84. "
  85. />
  86. </tippy>
  87. </span>
  88. </div>
  89. </div>
  90. <div v-if="showChildren || isFiltered" class="flex">
  91. <div
  92. class="flex w-1 transform transition cursor-nsResize ml-5.5 bg-dividerLight hover:scale-x-125 hover:bg-dividerDark"
  93. @click="toggleShowChildren()"
  94. ></div>
  95. <div class="flex flex-col flex-1 truncate">
  96. <CollectionsTeamsFolder
  97. v-for="(subFolder, subFolderIndex) in folder.children"
  98. :key="`subFolder-${subFolderIndex}`"
  99. :folder="subFolder"
  100. :folder-index="subFolderIndex"
  101. :collection-index="collectionIndex"
  102. :doc="doc"
  103. :save-request="saveRequest"
  104. :collections-type="collectionsType"
  105. :folder-path="`${folderPath}/${subFolderIndex}`"
  106. :picked="picked"
  107. @add-folder="$emit('add-folder', $event)"
  108. @edit-folder="$emit('edit-folder', $event)"
  109. @edit-request="$emit('edit-request', $event)"
  110. @update-team-collections="$emit('update-team-collections')"
  111. @select="$emit('select', $event)"
  112. @expand-collection="expandCollection"
  113. @remove-request="removeRequest"
  114. />
  115. <CollectionsTeamsRequest
  116. v-for="(request, index) in folder.requests"
  117. :key="`request-${index}`"
  118. :request="request.request"
  119. :collection-index="collectionIndex"
  120. :folder-index="folderIndex"
  121. :folder-name="folder.name"
  122. :request-index="request.id"
  123. :doc="doc"
  124. :save-request="saveRequest"
  125. :collections-type="collectionsType"
  126. :picked="picked"
  127. @edit-request="$emit('edit-request', $event)"
  128. @select="$emit('select', $event)"
  129. @remove-request="removeRequest"
  130. />
  131. <div
  132. v-if="
  133. (folder.children == undefined || folder.children.length === 0) &&
  134. (folder.requests == undefined || folder.requests.length === 0)
  135. "
  136. class="text-secondaryLight flex flex-col items-center justify-center p-4"
  137. >
  138. <img
  139. :src="`/images/states/${$colorMode.value}/pack.svg`"
  140. loading="lazy"
  141. class="inline-flex flex-col object-contain object-center w-16 h-16 mb-4"
  142. :alt="$t('empty.folder')"
  143. />
  144. <span class="text-center">
  145. {{ $t("empty.folder") }}
  146. </span>
  147. </div>
  148. </div>
  149. </div>
  150. <SmartConfirmModal
  151. :show="confirmRemove"
  152. :title="$t('confirm.remove_folder')"
  153. @hide-modal="confirmRemove = false"
  154. @resolve="removeFolder"
  155. />
  156. </div>
  157. </template>
  158. <script>
  159. import { defineComponent } from "@nuxtjs/composition-api"
  160. import * as teamUtils from "~/helpers/teams/utils"
  161. export default defineComponent({
  162. name: "Folder",
  163. props: {
  164. folder: { type: Object, default: () => {} },
  165. folderIndex: { type: Number, default: null },
  166. collectionIndex: { type: Number, default: null },
  167. folderPath: { type: String, default: null },
  168. doc: Boolean,
  169. saveRequest: Boolean,
  170. isFiltered: Boolean,
  171. collectionsType: { type: Object, default: () => {} },
  172. picked: { type: Object, default: () => {} },
  173. },
  174. data() {
  175. return {
  176. showChildren: false,
  177. confirmRemove: false,
  178. prevCursor: "",
  179. cursor: "",
  180. }
  181. },
  182. computed: {
  183. isSelected() {
  184. return (
  185. this.picked &&
  186. this.picked.pickedType === "teams-folder" &&
  187. this.picked.folderID === this.folder.id
  188. )
  189. },
  190. getCollectionIcon() {
  191. if (this.isSelected) return "check-circle"
  192. else if (!this.showChildren && !this.isFiltered) return "folder"
  193. else if (this.showChildren || this.isFiltered) return "folder-minus"
  194. else return "folder"
  195. },
  196. },
  197. methods: {
  198. toggleShowChildren() {
  199. if (this.$props.saveRequest)
  200. this.$emit("select", {
  201. picked: {
  202. pickedType: "teams-folder",
  203. folderID: this.folder.id,
  204. },
  205. })
  206. this.$emit("expand-collection", this.$props.folder.id)
  207. this.showChildren = !this.showChildren
  208. },
  209. removeFolder() {
  210. if (this.collectionsType.selectedTeam.myRole !== "VIEWER") {
  211. // Cancel pick if picked collection folder was deleted
  212. if (
  213. this.picked &&
  214. this.picked.pickedType === "teams-folder" &&
  215. this.picked.folderID === this.folder.id
  216. ) {
  217. this.$emit("select", { picked: null })
  218. }
  219. teamUtils
  220. .deleteCollection(this.$apollo, this.folder.id)
  221. .then(() => {
  222. this.$toast.success(this.$t("state.deleted"))
  223. this.$emit("update-team-collections")
  224. })
  225. .catch((e) => {
  226. this.$toast.error(this.$t("error.something_went_wrong"))
  227. console.error(e)
  228. })
  229. this.$emit("update-team-collections")
  230. }
  231. },
  232. expandCollection(collectionID) {
  233. this.$emit("expand-collection", collectionID)
  234. },
  235. removeRequest({ collectionIndex, folderName, requestIndex }) {
  236. this.$emit("remove-request", {
  237. collectionIndex,
  238. folderName,
  239. requestIndex,
  240. })
  241. },
  242. },
  243. })
  244. </script>