SaveRequest.vue 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. <template>
  2. <SmartModal
  3. v-if="show"
  4. :title="`${$t('collection.save_as')}`"
  5. @close="hideModal"
  6. >
  7. <template #body>
  8. <div class="flex flex-col px-2">
  9. <div class="flex relative">
  10. <input
  11. id="selectLabelSaveReq"
  12. v-model="requestName"
  13. v-focus
  14. class="input floating-input"
  15. placeholder=" "
  16. type="text"
  17. autocomplete="off"
  18. @keyup.enter="saveRequestAs"
  19. />
  20. <label for="selectLabelSaveReq">
  21. {{ $t("request.name") }}
  22. </label>
  23. </div>
  24. <label class="p-4">
  25. {{ $t("collection.select_location") }}
  26. </label>
  27. <CollectionsGraphql
  28. v-if="mode === 'graphql'"
  29. :doc="false"
  30. :show-coll-actions="false"
  31. :picked="picked"
  32. :saving-mode="true"
  33. @select="onSelect"
  34. />
  35. <Collections
  36. v-else
  37. :picked="picked"
  38. :save-request="true"
  39. @select="onSelect"
  40. @update-collection="updateColl"
  41. @update-coll-type="onUpdateCollType"
  42. />
  43. </div>
  44. </template>
  45. <template #footer>
  46. <span>
  47. <ButtonPrimary
  48. :label="`${$t('action.save')}`"
  49. @click.native="saveRequestAs"
  50. />
  51. <ButtonSecondary
  52. :label="`${$t('action.cancel')}`"
  53. @click.native="hideModal"
  54. />
  55. </span>
  56. </template>
  57. </SmartModal>
  58. </template>
  59. <script setup lang="ts">
  60. import { reactive, ref, useContext, watch } from "@nuxtjs/composition-api"
  61. import { isHoppRESTRequest } from "~/helpers/types/HoppRESTRequest"
  62. import {
  63. editGraphqlRequest,
  64. editRESTRequest,
  65. saveGraphqlRequestAs,
  66. saveRESTRequestAs,
  67. } from "~/newstore/collections"
  68. import { getGQLSession, useGQLRequestName } from "~/newstore/GQLSession"
  69. import {
  70. getRESTRequest,
  71. setRESTSaveContext,
  72. useRESTRequestName,
  73. } from "~/newstore/RESTSession"
  74. import * as teamUtils from "~/helpers/teams/utils"
  75. import { apolloClient } from "~/helpers/apollo"
  76. import { HoppGQLRequest } from "~/helpers/types/HoppGQLRequest"
  77. type CollectionType =
  78. | {
  79. type: "my-collections"
  80. }
  81. | {
  82. type: "team-collections"
  83. // TODO: Figure this type out
  84. selectedTeam: {
  85. id: string
  86. }
  87. }
  88. type Picked =
  89. | {
  90. pickedType: "my-request"
  91. folderPath: string
  92. requestIndex: number
  93. }
  94. | {
  95. pickedType: "my-folder"
  96. folderPath: string
  97. }
  98. | {
  99. pickedType: "my-collection"
  100. collectionIndex: number
  101. }
  102. | {
  103. pickedType: "teams-request"
  104. requestID: string
  105. }
  106. | {
  107. pickedType: "teams-folder"
  108. folderID: string
  109. }
  110. | {
  111. pickedType: "teams-collection"
  112. collectionID: string
  113. }
  114. | {
  115. pickedType: "gql-my-request"
  116. folderPath: string
  117. requestIndex: number
  118. }
  119. | {
  120. pickedType: "gql-my-folder"
  121. folderPath: string
  122. }
  123. | {
  124. pickedType: "gql-my-collection"
  125. collectionIndex: number
  126. }
  127. const props = defineProps<{
  128. mode: "rest" | "graphql"
  129. show: boolean
  130. }>()
  131. const emit = defineEmits<{
  132. (e: "hide-modal"): void
  133. }>()
  134. const {
  135. $toast,
  136. app: { i18n },
  137. } = useContext()
  138. const t = i18n.t.bind(i18n)
  139. // TODO: Use a better implementation with computed ?
  140. // This implementation can't work across updates to mode prop (which won't happen tho)
  141. const requestName =
  142. props.mode === "rest" ? useRESTRequestName() : useGQLRequestName()
  143. const requestData = reactive({
  144. name: requestName,
  145. collectionIndex: undefined as number | undefined,
  146. folderName: undefined as number | undefined,
  147. requestIndex: undefined as number | undefined,
  148. })
  149. const collectionsType = ref<CollectionType>({
  150. type: "my-collections",
  151. })
  152. // TODO: Figure this type out
  153. const picked = ref<Picked | null>(null)
  154. // Resets
  155. watch(
  156. () => requestData.collectionIndex,
  157. () => {
  158. requestData.folderName = undefined
  159. requestData.requestIndex = undefined
  160. }
  161. )
  162. watch(
  163. () => requestData.folderName,
  164. () => {
  165. requestData.requestIndex = undefined
  166. }
  167. )
  168. // All the methods
  169. const onUpdateCollType = (newCollType: CollectionType) => {
  170. collectionsType.value = newCollType
  171. }
  172. const onSelect = ({ picked: pickedVal }: { picked: Picked | null }) => {
  173. picked.value = pickedVal
  174. }
  175. const hideModal = () => {
  176. picked.value = null
  177. emit("hide-modal")
  178. }
  179. const saveRequestAs = async () => {
  180. if (!requestName.value) {
  181. $toast.error(`${t("error.empty_req_name")}`, {
  182. icon: "error_outline",
  183. })
  184. return
  185. }
  186. if (picked.value === null) {
  187. $toast.error(`${t("collection.select")}`, {
  188. icon: "error_outline",
  189. })
  190. return
  191. }
  192. const requestUpdated =
  193. props.mode === "rest" ? getRESTRequest() : getGQLSession().request
  194. // // Filter out all REST file inputs
  195. // if (this.mode === "rest" && requestUpdated.bodyParams) {
  196. // requestUpdated.bodyParams = requestUpdated.bodyParams.map((param) =>
  197. // param?.value?.[0] instanceof File ? { ...param, value: "" } : param
  198. // )
  199. // }
  200. if (picked.value.pickedType === "my-request") {
  201. if (!isHoppRESTRequest(requestUpdated))
  202. throw new Error("requestUpdated is not a REST Request")
  203. editRESTRequest(
  204. picked.value.folderPath,
  205. picked.value.requestIndex,
  206. requestUpdated
  207. )
  208. setRESTSaveContext({
  209. originLocation: "user-collection",
  210. folderPath: picked.value.folderPath,
  211. requestIndex: picked.value.requestIndex,
  212. })
  213. requestSaved()
  214. } else if (picked.value.pickedType === "my-folder") {
  215. if (!isHoppRESTRequest(requestUpdated))
  216. throw new Error("requestUpdated is not a REST Request")
  217. const insertionIndex = saveRESTRequestAs(
  218. picked.value.folderPath,
  219. requestUpdated
  220. )
  221. setRESTSaveContext({
  222. originLocation: "user-collection",
  223. folderPath: picked.value.folderPath,
  224. requestIndex: insertionIndex,
  225. })
  226. requestSaved()
  227. } else if (picked.value.pickedType === "my-collection") {
  228. if (!isHoppRESTRequest(requestUpdated))
  229. throw new Error("requestUpdated is not a REST Request")
  230. const insertionIndex = saveRESTRequestAs(
  231. `${picked.value.collectionIndex}`,
  232. requestUpdated
  233. )
  234. setRESTSaveContext({
  235. originLocation: "user-collection",
  236. folderPath: `${picked.value.collectionIndex}`,
  237. requestIndex: insertionIndex,
  238. })
  239. requestSaved()
  240. } else if (picked.value.pickedType === "teams-request") {
  241. if (!isHoppRESTRequest(requestUpdated))
  242. throw new Error("requestUpdated is not a REST Request")
  243. if (collectionsType.value.type !== "team-collections")
  244. throw new Error("Collections Type mismatch")
  245. teamUtils
  246. .overwriteRequestTeams(
  247. apolloClient,
  248. JSON.stringify(requestUpdated),
  249. requestUpdated.name,
  250. picked.value.requestID
  251. )
  252. .then(() => {
  253. requestSaved()
  254. })
  255. .catch((error) => {
  256. $toast.error(t("profile.no_permission").toString(), {
  257. icon: "error_outline",
  258. })
  259. throw new Error(error)
  260. })
  261. setRESTSaveContext({
  262. originLocation: "team-collection",
  263. requestID: picked.value.requestID,
  264. })
  265. } else if (picked.value.pickedType === "teams-folder") {
  266. if (!isHoppRESTRequest(requestUpdated))
  267. throw new Error("requestUpdated is not a REST Request")
  268. if (collectionsType.value.type !== "team-collections")
  269. throw new Error("Collections Type mismatch")
  270. try {
  271. const req = await teamUtils.saveRequestAsTeams(
  272. apolloClient,
  273. JSON.stringify(requestUpdated),
  274. requestUpdated.name,
  275. collectionsType.value.selectedTeam.id,
  276. picked.value.folderID
  277. )
  278. if (req && req.id) {
  279. setRESTSaveContext({
  280. originLocation: "team-collection",
  281. requestID: req.id,
  282. teamID: collectionsType.value.selectedTeam.id,
  283. collectionID: picked.value.folderID,
  284. })
  285. }
  286. requestSaved()
  287. } catch (error) {
  288. $toast.error(t("profile.no_permission").toString(), {
  289. icon: "error_outline",
  290. })
  291. console.error(error)
  292. }
  293. } else if (picked.value.pickedType === "teams-collection") {
  294. if (!isHoppRESTRequest(requestUpdated))
  295. throw new Error("requestUpdated is not a REST Request")
  296. if (collectionsType.value.type !== "team-collections")
  297. throw new Error("Collections Type mismatch")
  298. try {
  299. const req = await teamUtils.saveRequestAsTeams(
  300. apolloClient,
  301. JSON.stringify(requestUpdated),
  302. requestUpdated.name,
  303. collectionsType.value.selectedTeam.id,
  304. picked.value.collectionID
  305. )
  306. if (req && req.id) {
  307. setRESTSaveContext({
  308. originLocation: "team-collection",
  309. requestID: req.id,
  310. teamID: collectionsType.value.selectedTeam.id,
  311. collectionID: picked.value.collectionID,
  312. })
  313. }
  314. requestSaved()
  315. } catch (error) {
  316. $toast.error(t("profile.no_permission").toString(), {
  317. icon: "error_outline",
  318. })
  319. console.error(error)
  320. }
  321. } else if (picked.value.pickedType === "gql-my-request") {
  322. // TODO: Check for GQL request ?
  323. editGraphqlRequest(
  324. picked.value.folderPath,
  325. picked.value.requestIndex,
  326. requestUpdated as HoppGQLRequest
  327. )
  328. requestSaved()
  329. } else if (picked.value.pickedType === "gql-my-folder") {
  330. // TODO: Check for GQL request ?
  331. saveGraphqlRequestAs(
  332. picked.value.folderPath,
  333. requestUpdated as HoppGQLRequest
  334. )
  335. requestSaved()
  336. } else if (picked.value.pickedType === "gql-my-collection") {
  337. // TODO: Check for GQL request ?
  338. saveGraphqlRequestAs(
  339. `${picked.value.collectionIndex}`,
  340. requestUpdated as HoppGQLRequest
  341. )
  342. requestSaved()
  343. }
  344. }
  345. const requestSaved = () => {
  346. $toast.success(`${t("request.added")}`, {
  347. icon: "post_add",
  348. })
  349. hideModal()
  350. }
  351. const updateColl = (ev: CollectionType["type"]) => {
  352. collectionsType.value.type = ev
  353. }
  354. </script>