index.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. <template>
  2. <div :class="{ 'rounded border border-divider': saveRequest }">
  3. <div
  4. class="sticky z-10 flex flex-col border-b rounded-t divide-y divide-dividerLight bg-primary border-dividerLight"
  5. :style="saveRequest ? 'top: calc(-1 * var(--font-size-body))' : 'top: 0'"
  6. >
  7. <div v-if="!saveRequest" class="flex flex-col">
  8. <input
  9. v-model="filterText"
  10. type="search"
  11. autocomplete="off"
  12. :placeholder="$t('action.search')"
  13. class="py-2 pl-4 pr-2 bg-transparent"
  14. />
  15. </div>
  16. <CollectionsChooseType
  17. :collections-type="collectionsType"
  18. :show="showTeamCollections"
  19. :doc="doc"
  20. @update-collection-type="updateCollectionType"
  21. @update-selected-team="updateSelectedTeam"
  22. />
  23. <div class="flex justify-between flex-1">
  24. <ButtonSecondary
  25. v-if="
  26. collectionsType.type == 'team-collections' &&
  27. (collectionsType.selectedTeam == undefined ||
  28. collectionsType.selectedTeam.myRole == 'VIEWER')
  29. "
  30. v-tippy="{ theme: 'tooltip' }"
  31. disabled
  32. class="!rounded-none"
  33. svg="plus"
  34. :title="$t('team.no_access')"
  35. :label="$t('action.new')"
  36. />
  37. <ButtonSecondary
  38. v-else
  39. svg="plus"
  40. :label="$t('action.new')"
  41. class="!rounded-none"
  42. @click.native="displayModalAdd(true)"
  43. />
  44. <span class="flex">
  45. <ButtonSecondary
  46. v-tippy="{ theme: 'tooltip' }"
  47. to="https://docs.hoppscotch.io/features/collections"
  48. blank
  49. :title="$t('app.wiki')"
  50. svg="help-circle"
  51. />
  52. <ButtonSecondary
  53. v-if="!saveRequest"
  54. v-tippy="{ theme: 'tooltip' }"
  55. :disabled="
  56. collectionsType.type == 'team-collections' &&
  57. collectionsType.selectedTeam == undefined
  58. "
  59. svg="archive"
  60. :title="$t('modal.import_export')"
  61. @click.native="displayModalImportExport(true)"
  62. />
  63. </span>
  64. </div>
  65. </div>
  66. <div class="flex flex-col flex-1">
  67. <component
  68. :is="
  69. collectionsType.type == 'my-collections'
  70. ? 'CollectionsMyCollection'
  71. : 'CollectionsTeamsCollection'
  72. "
  73. v-for="(collection, index) in filteredCollections"
  74. :key="`collection-${index}`"
  75. :collection-index="index"
  76. :collection="collection"
  77. :doc="doc"
  78. :is-filtered="filterText.length > 0"
  79. :selected="selected.some((coll) => coll == collection)"
  80. :save-request="saveRequest"
  81. :collections-type="collectionsType"
  82. :picked="picked"
  83. :loading-collection-i-ds="loadingCollectionIDs"
  84. @edit-collection="editCollection(collection, index)"
  85. @add-folder="addFolder($event)"
  86. @edit-folder="editFolder($event)"
  87. @edit-request="editRequest($event)"
  88. @duplicate-request="duplicateRequest($event)"
  89. @update-team-collections="updateTeamCollections"
  90. @select-collection="$emit('use-collection', collection)"
  91. @unselect-collection="$emit('remove-collection', collection)"
  92. @select="$emit('select', $event)"
  93. @expand-collection="expandCollection"
  94. @remove-collection="removeCollection"
  95. @remove-request="removeRequest"
  96. />
  97. </div>
  98. <div
  99. v-if="loadingCollectionIDs.includes('root')"
  100. class="flex flex-col items-center justify-center p-4"
  101. >
  102. <SmartSpinner class="my-4" />
  103. <span class="text-secondaryLight">{{ $t("state.loading") }}</span>
  104. </div>
  105. <div
  106. v-else-if="filteredCollections.length === 0 && filterText.length === 0"
  107. class="flex flex-col items-center justify-center p-4 text-secondaryLight"
  108. >
  109. <img
  110. :src="`/images/states/${$colorMode.value}/pack.svg`"
  111. loading="lazy"
  112. class="inline-flex flex-col object-contain object-center w-16 h-16 my-4"
  113. :alt="$t('empty.collections')"
  114. />
  115. <span class="pb-4 text-center">
  116. {{ $t("empty.collections") }}
  117. </span>
  118. <ButtonSecondary
  119. v-if="
  120. collectionsType.type == 'team-collections' &&
  121. (collectionsType.selectedTeam == undefined ||
  122. collectionsType.selectedTeam.myRole == 'VIEWER')
  123. "
  124. v-tippy="{ theme: 'tooltip' }"
  125. :title="$t('team.no_access')"
  126. :label="$t('add.new')"
  127. class="mb-4"
  128. filled
  129. />
  130. <ButtonSecondary
  131. v-else
  132. :label="$t('add.new')"
  133. filled
  134. class="mb-4"
  135. @click.native="displayModalAdd(true)"
  136. />
  137. </div>
  138. <div
  139. v-if="filterText.length !== 0 && filteredCollections.length === 0"
  140. class="flex flex-col items-center justify-center p-4 text-secondaryLight"
  141. >
  142. <i class="pb-2 opacity-75 material-icons">manage_search</i>
  143. <span class="my-2 text-center">
  144. {{ $t("state.nothing_found") }} "{{ filterText }}"
  145. </span>
  146. </div>
  147. <CollectionsAdd
  148. :show="showModalAdd"
  149. @submit="addNewRootCollection"
  150. @hide-modal="displayModalAdd(false)"
  151. />
  152. <CollectionsEdit
  153. :show="showModalEdit"
  154. :editing-collection-name="
  155. editingCollection
  156. ? editingCollection.name || editingCollection.title
  157. : ''
  158. "
  159. @hide-modal="displayModalEdit(false)"
  160. @submit="updateEditingCollection"
  161. />
  162. <CollectionsAddFolder
  163. :show="showModalAddFolder"
  164. :folder="editingFolder"
  165. :folder-path="editingFolderPath"
  166. @add-folder="onAddFolder($event)"
  167. @hide-modal="displayModalAddFolder(false)"
  168. />
  169. <CollectionsEditFolder
  170. :show="showModalEditFolder"
  171. :editing-folder-name="
  172. editingFolder ? editingFolder.name || editingFolder.title : ''
  173. "
  174. @submit="updateEditingFolder"
  175. @hide-modal="displayModalEditFolder(false)"
  176. />
  177. <CollectionsEditRequest
  178. :show="showModalEditRequest"
  179. :editing-request-name="editingRequest ? editingRequest.name : ''"
  180. @submit="updateEditingRequest"
  181. @hide-modal="displayModalEditRequest(false)"
  182. />
  183. <CollectionsImportExport
  184. :show="showModalImportExport"
  185. :collections-type="collectionsType"
  186. @hide-modal="displayModalImportExport(false)"
  187. @update-team-collections="updateTeamCollections"
  188. />
  189. </div>
  190. </template>
  191. <script>
  192. import cloneDeep from "lodash/cloneDeep"
  193. import { defineComponent } from "@nuxtjs/composition-api"
  194. import { makeCollection } from "@hoppscotch/data"
  195. import * as E from "fp-ts/Either"
  196. import CollectionsMyCollection from "./my/Collection.vue"
  197. import CollectionsTeamsCollection from "./teams/Collection.vue"
  198. import { currentUser$ } from "~/helpers/fb/auth"
  199. import TeamCollectionAdapter from "~/helpers/teams/TeamCollectionAdapter"
  200. import {
  201. restCollections$,
  202. addRESTCollection,
  203. editRESTCollection,
  204. addRESTFolder,
  205. removeRESTCollection,
  206. editRESTFolder,
  207. removeRESTRequest,
  208. editRESTRequest,
  209. saveRESTRequestAs,
  210. } from "~/newstore/collections"
  211. import {
  212. useReadonlyStream,
  213. useStreamSubscriber,
  214. } from "~/helpers/utils/composables"
  215. import { runMutation } from "~/helpers/backend/GQLClient"
  216. import {
  217. CreateChildCollectionDocument,
  218. CreateNewRootCollectionDocument,
  219. CreateRequestInCollectionDocument,
  220. DeleteCollectionDocument,
  221. DeleteRequestDocument,
  222. RenameCollectionDocument,
  223. UpdateRequestDocument,
  224. } from "~/helpers/backend/graphql"
  225. export default defineComponent({
  226. components: {
  227. CollectionsMyCollection,
  228. CollectionsTeamsCollection,
  229. },
  230. props: {
  231. doc: Boolean,
  232. selected: { type: Array, default: () => [] },
  233. saveRequest: Boolean,
  234. picked: { type: Object, default: () => {} },
  235. },
  236. setup() {
  237. const { subscribeToStream } = useStreamSubscriber()
  238. return {
  239. subscribeTo: subscribeToStream,
  240. collections: useReadonlyStream(restCollections$, []),
  241. currentUser: useReadonlyStream(currentUser$, null),
  242. }
  243. },
  244. data() {
  245. return {
  246. showModalAdd: false,
  247. showModalEdit: false,
  248. showModalImportExport: false,
  249. showModalAddFolder: false,
  250. showModalEditFolder: false,
  251. showModalEditRequest: false,
  252. editingCollection: undefined,
  253. editingCollectionIndex: undefined,
  254. editingFolder: undefined,
  255. editingFolderName: undefined,
  256. editingFolderIndex: undefined,
  257. editingFolderPath: undefined,
  258. editingRequest: undefined,
  259. editingRequestIndex: undefined,
  260. filterText: "",
  261. collectionsType: {
  262. type: "my-collections",
  263. selectedTeam: undefined,
  264. },
  265. teamCollectionAdapter: new TeamCollectionAdapter(null),
  266. teamCollectionsNew: [],
  267. loadingCollectionIDs: [],
  268. }
  269. },
  270. computed: {
  271. showTeamCollections() {
  272. if (this.currentUser == null) {
  273. return false
  274. }
  275. return true
  276. },
  277. filteredCollections() {
  278. const collections =
  279. this.collectionsType.type === "my-collections"
  280. ? this.collections
  281. : this.teamCollectionsNew
  282. if (!this.filterText) {
  283. return collections
  284. }
  285. if (this.collectionsType.type === "team-collections") {
  286. return []
  287. }
  288. const filterText = this.filterText.toLowerCase()
  289. const filteredCollections = []
  290. for (const collection of collections) {
  291. const filteredRequests = []
  292. const filteredFolders = []
  293. for (const request of collection.requests) {
  294. if (request.name.toLowerCase().includes(filterText))
  295. filteredRequests.push(request)
  296. }
  297. for (const folder of this.collectionsType.type === "team-collections"
  298. ? collection.children
  299. : collection.folders) {
  300. const filteredFolderRequests = []
  301. for (const request of folder.requests) {
  302. if (request.name.toLowerCase().includes(filterText))
  303. filteredFolderRequests.push(request)
  304. }
  305. if (filteredFolderRequests.length > 0) {
  306. const filteredFolder = Object.assign({}, folder)
  307. filteredFolder.requests = filteredFolderRequests
  308. filteredFolders.push(filteredFolder)
  309. }
  310. }
  311. if (
  312. filteredRequests.length + filteredFolders.length > 0 ||
  313. collection.name.toLowerCase().includes(filterText)
  314. ) {
  315. const filteredCollection = Object.assign({}, collection)
  316. filteredCollection.requests = filteredRequests
  317. filteredCollection.folders = filteredFolders
  318. filteredCollections.push(filteredCollection)
  319. }
  320. }
  321. return filteredCollections
  322. },
  323. },
  324. watch: {
  325. "collectionsType.type": function emitstuff() {
  326. this.$emit("update-collection", this.$data.collectionsType.type)
  327. },
  328. "collectionsType.selectedTeam"(value) {
  329. if (value?.id) this.teamCollectionAdapter.changeTeamID(value.id)
  330. },
  331. currentUser(newValue) {
  332. if (!newValue) this.updateCollectionType("my-collections")
  333. },
  334. },
  335. mounted() {
  336. this.subscribeTo(this.teamCollectionAdapter.collections$, (colls) => {
  337. this.teamCollectionsNew = cloneDeep(colls)
  338. })
  339. this.subscribeTo(
  340. this.teamCollectionAdapter.loadingCollections$,
  341. (collectionsIDs) => {
  342. this.loadingCollectionIDs = collectionsIDs
  343. }
  344. )
  345. },
  346. methods: {
  347. updateTeamCollections() {
  348. // TODO: Remove this at some point
  349. },
  350. updateSelectedTeam(newSelectedTeam) {
  351. this.collectionsType.selectedTeam = newSelectedTeam
  352. this.$emit("update-coll-type", this.collectionsType)
  353. },
  354. updateCollectionType(newCollectionType) {
  355. this.collectionsType.type = newCollectionType
  356. this.$emit("update-coll-type", this.collectionsType)
  357. },
  358. // Intented to be called by the CollectionAdd modal submit event
  359. addNewRootCollection(name) {
  360. if (this.collectionsType.type === "my-collections") {
  361. addRESTCollection(
  362. makeCollection({
  363. name,
  364. folders: [],
  365. requests: [],
  366. })
  367. )
  368. } else if (
  369. this.collectionsType.type === "team-collections" &&
  370. this.collectionsType.selectedTeam.myRole !== "VIEWER"
  371. ) {
  372. runMutation(CreateNewRootCollectionDocument, {
  373. title: name,
  374. teamID: this.collectionsType.selectedTeam.id,
  375. })().then((result) => {
  376. if (E.isLeft(result)) {
  377. if (result.left.error === "team_coll/short_title")
  378. this.$toast.error(this.$t("collection.name_length_insufficient"))
  379. else this.$toast.error(this.$t("error.something_went_wrong"))
  380. console.error(result.left.error)
  381. } else {
  382. this.$toast.success(this.$t("collection.created"))
  383. }
  384. })
  385. }
  386. this.displayModalAdd(false)
  387. },
  388. // Intented to be called by CollectionEdit modal submit event
  389. updateEditingCollection(newName) {
  390. if (!newName) {
  391. this.$toast.error(this.$t("collection.invalid_name"))
  392. return
  393. }
  394. if (this.collectionsType.type === "my-collections") {
  395. const collectionUpdated = {
  396. ...this.editingCollection,
  397. name: newName,
  398. }
  399. editRESTCollection(this.editingCollectionIndex, collectionUpdated)
  400. } else if (
  401. this.collectionsType.type === "team-collections" &&
  402. this.collectionsType.selectedTeam.myRole !== "VIEWER"
  403. ) {
  404. runMutation(RenameCollectionDocument, {
  405. collectionID: this.editingCollection.id,
  406. newTitle: newName,
  407. })().then((result) => {
  408. if (E.isLeft(result)) {
  409. this.$toast.error(this.$t("error.something_went_wrong"))
  410. console.error(e)
  411. } else {
  412. this.$toast.success(this.$t("collection.renamed"))
  413. }
  414. })
  415. }
  416. this.displayModalEdit(false)
  417. },
  418. // Intended to be called by CollectionEditFolder modal submit event
  419. updateEditingFolder(name) {
  420. if (this.collectionsType.type === "my-collections") {
  421. editRESTFolder(this.editingFolderPath, { ...this.editingFolder, name })
  422. } else if (
  423. this.collectionsType.type === "team-collections" &&
  424. this.collectionsType.selectedTeam.myRole !== "VIEWER"
  425. ) {
  426. runMutation(RenameCollectionDocument, {
  427. collectionID: this.editingFolder.id,
  428. newTitle: name,
  429. })().then((result) => {
  430. if (E.isLeft(result)) {
  431. this.$toast.error(this.$t("error.something_went_wrong"))
  432. console.error(e)
  433. } else {
  434. this.$toast.success(this.$t("folder.renamed"))
  435. }
  436. })
  437. }
  438. this.displayModalEditFolder(false)
  439. },
  440. // Intented to by called by CollectionsEditRequest modal submit event
  441. updateEditingRequest(requestUpdateData) {
  442. const requestUpdated = {
  443. ...this.editingRequest,
  444. name: requestUpdateData.name || this.editingRequest.name,
  445. }
  446. if (this.collectionsType.type === "my-collections") {
  447. editRESTRequest(
  448. this.editingFolderPath,
  449. this.editingRequestIndex,
  450. requestUpdated
  451. )
  452. } else if (
  453. this.collectionsType.type === "team-collections" &&
  454. this.collectionsType.selectedTeam.myRole !== "VIEWER"
  455. ) {
  456. const requestName = requestUpdateData.name || this.editingRequest.name
  457. runMutation(UpdateRequestDocument, {
  458. data: {
  459. request: JSON.stringify(requestUpdated),
  460. title: requestName,
  461. },
  462. requestID: this.editingRequestIndex,
  463. })().then((result) => {
  464. if (E.isLeft(result)) {
  465. this.$toast.error(this.$t("error.something_went_wrong"))
  466. console.error(e)
  467. } else {
  468. this.$toast.success(this.$t("request.renamed"))
  469. this.$emit("update-team-collections")
  470. }
  471. })
  472. }
  473. this.displayModalEditRequest(false)
  474. },
  475. displayModalAdd(shouldDisplay) {
  476. this.showModalAdd = shouldDisplay
  477. },
  478. displayModalEdit(shouldDisplay) {
  479. this.showModalEdit = shouldDisplay
  480. if (!shouldDisplay) this.resetSelectedData()
  481. },
  482. displayModalImportExport(shouldDisplay) {
  483. this.showModalImportExport = shouldDisplay
  484. },
  485. displayModalAddFolder(shouldDisplay) {
  486. this.showModalAddFolder = shouldDisplay
  487. if (!shouldDisplay) this.resetSelectedData()
  488. },
  489. displayModalEditFolder(shouldDisplay) {
  490. this.showModalEditFolder = shouldDisplay
  491. if (!shouldDisplay) this.resetSelectedData()
  492. },
  493. displayModalEditRequest(shouldDisplay) {
  494. this.showModalEditRequest = shouldDisplay
  495. if (!shouldDisplay) this.resetSelectedData()
  496. },
  497. editCollection(collection, collectionIndex) {
  498. this.$data.editingCollection = collection
  499. this.$data.editingCollectionIndex = collectionIndex
  500. this.displayModalEdit(true)
  501. },
  502. onAddFolder({ name, folder, path }) {
  503. if (this.collectionsType.type === "my-collections") {
  504. addRESTFolder(name, path)
  505. } else if (this.collectionsType.type === "team-collections") {
  506. if (this.collectionsType.selectedTeam.myRole !== "VIEWER") {
  507. runMutation(CreateChildCollectionDocument, {
  508. childTitle: name,
  509. collectionID: folder.id,
  510. })().then((result) => {
  511. if (E.isLeft(result)) {
  512. if (result.left.error === "team_coll/short_title")
  513. this.$toast.error(this.$t("folder.name_length_insufficient"))
  514. else this.$toast.error(this.$t("error.something_went_wrong"))
  515. console.error(result.left.error)
  516. } else {
  517. this.$toast.success(this.$t("folder.created"))
  518. this.$emit("update-team-collections")
  519. }
  520. })
  521. }
  522. }
  523. this.displayModalAddFolder(false)
  524. },
  525. addFolder(payload) {
  526. const { folder, path } = payload
  527. this.$data.editingFolder = folder
  528. this.$data.editingFolderPath = path
  529. this.displayModalAddFolder(true)
  530. },
  531. editFolder(payload) {
  532. const { collectionIndex, folder, folderIndex, folderPath } = payload
  533. this.$data.editingCollectionIndex = collectionIndex
  534. this.$data.editingFolder = folder
  535. this.$data.editingFolderIndex = folderIndex
  536. this.$data.editingFolderPath = folderPath
  537. this.$data.collectionsType = this.collectionsType
  538. this.displayModalEditFolder(true)
  539. },
  540. editRequest(payload) {
  541. const {
  542. collectionIndex,
  543. folderIndex,
  544. folderName,
  545. request,
  546. requestIndex,
  547. folderPath,
  548. } = payload
  549. this.$data.editingCollectionIndex = collectionIndex
  550. this.$data.editingFolderIndex = folderIndex
  551. this.$data.editingFolderName = folderName
  552. this.$data.editingRequest = request
  553. this.$data.editingRequestIndex = requestIndex
  554. this.editingFolderPath = folderPath
  555. this.$emit("select-request", requestIndex)
  556. this.displayModalEditRequest(true)
  557. },
  558. resetSelectedData() {
  559. this.$data.editingCollection = undefined
  560. this.$data.editingCollectionIndex = undefined
  561. this.$data.editingFolder = undefined
  562. this.$data.editingFolderIndex = undefined
  563. this.$data.editingRequest = undefined
  564. this.$data.editingRequestIndex = undefined
  565. },
  566. expandCollection(collectionID) {
  567. this.teamCollectionAdapter.expandCollection(collectionID)
  568. },
  569. removeCollection({ collectionsType, collectionIndex, collectionID }) {
  570. if (collectionsType.type === "my-collections") {
  571. // Cancel pick if picked collection is deleted
  572. if (
  573. this.picked &&
  574. this.picked.pickedType === "my-collection" &&
  575. this.picked.collectionIndex === collectionIndex
  576. ) {
  577. this.$emit("select", { picked: null })
  578. }
  579. removeRESTCollection(collectionIndex)
  580. this.$toast.success(this.$t("state.deleted"))
  581. } else if (collectionsType.type === "team-collections") {
  582. // Cancel pick if picked collection is deleted
  583. if (
  584. this.picked &&
  585. this.picked.pickedType === "teams-collection" &&
  586. this.picked.collectionID === collectionID
  587. ) {
  588. this.$emit("select", { picked: null })
  589. }
  590. if (collectionsType.selectedTeam.myRole !== "VIEWER") {
  591. runMutation(DeleteCollectionDocument, {
  592. collectionID,
  593. })().then((result) => {
  594. if (E.isLeft(result)) {
  595. this.$toast.error(this.$t("error.something_went_wrong"))
  596. console.error(e)
  597. } else {
  598. this.$toast.success(this.$t("state.deleted"))
  599. }
  600. })
  601. }
  602. }
  603. },
  604. removeRequest({ requestIndex, folderPath }) {
  605. if (this.collectionsType.type === "my-collections") {
  606. // Cancel pick if the picked item is being deleted
  607. if (
  608. this.picked &&
  609. this.picked.pickedType === "my-request" &&
  610. this.picked.folderPath === folderPath &&
  611. this.picked.requestIndex === requestIndex
  612. ) {
  613. this.$emit("select", { picked: null })
  614. }
  615. removeRESTRequest(folderPath, requestIndex)
  616. this.$toast.success(this.$t("state.deleted"))
  617. } else if (this.collectionsType.type === "team-collections") {
  618. // Cancel pick if the picked item is being deleted
  619. if (
  620. this.picked &&
  621. this.picked.pickedType === "teams-request" &&
  622. this.picked.requestID === requestIndex
  623. ) {
  624. this.$emit("select", { picked: null })
  625. }
  626. runMutation(DeleteRequestDocument, {
  627. requestID: requestIndex,
  628. })().then((result) => {
  629. if (E.isLeft(result)) {
  630. this.$toast.error(this.$t("error.something_went_wrong"))
  631. console.error(e)
  632. } else {
  633. this.$toast.success(this.$t("state.deleted"))
  634. }
  635. })
  636. }
  637. },
  638. duplicateRequest({ folderPath, request, collectionID }) {
  639. if (this.collectionsType.type === "team-collections") {
  640. const newReq = {
  641. ...cloneDeep(request),
  642. name: `${request.name} - ${this.$t("action.duplicate")}`,
  643. }
  644. // Error handling ?
  645. runMutation(CreateRequestInCollectionDocument, {
  646. collectionID,
  647. data: {
  648. request: JSON.stringify(newReq),
  649. teamID: this.collectionsType.selectedTeam.id,
  650. title: `${request.name} - ${this.$t("action.duplicate")}`,
  651. },
  652. })()
  653. } else if (this.collectionsType.type === "my-collections") {
  654. saveRESTRequestAs(folderPath, {
  655. ...cloneDeep(request),
  656. name: `${request.name} - ${this.$t("action.duplicate")}`,
  657. })
  658. }
  659. },
  660. },
  661. })
  662. </script>