index.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <template>
  2. <Splitpanes
  3. class="smart-splitter"
  4. :rtl="SIDEBAR_ON_LEFT && windowInnerWidth.x.value >= 768"
  5. :class="{
  6. '!flex-row-reverse': SIDEBAR_ON_LEFT && windowInnerWidth.x.value >= 768,
  7. }"
  8. :horizontal="!(windowInnerWidth.x.value >= 768)"
  9. >
  10. <Pane size="75" min-size="65" class="hide-scrollbar !overflow-auto">
  11. <Splitpanes class="smart-splitter" :horizontal="COLUMN_LAYOUT">
  12. <Pane
  13. :size="COLUMN_LAYOUT ? 45 : 50"
  14. class="hide-scrollbar !overflow-auto"
  15. >
  16. <HttpRequest />
  17. <SmartTabs styles="sticky bg-primary top-upperPrimaryStickyFold z-10">
  18. <SmartTab
  19. :id="'params'"
  20. :label="`${$t('tab.parameters')}`"
  21. :selected="true"
  22. :info="`${newActiveParamsCount$}`"
  23. >
  24. <HttpParameters />
  25. </SmartTab>
  26. <SmartTab :id="'bodyParams'" :label="`${$t('tab.body')}`">
  27. <HttpBody />
  28. </SmartTab>
  29. <SmartTab
  30. :id="'headers'"
  31. :label="`${$t('tab.headers')}`"
  32. :info="`${newActiveHeadersCount$}`"
  33. >
  34. <HttpHeaders />
  35. </SmartTab>
  36. <SmartTab
  37. :id="'authorization'"
  38. :label="`${$t('tab.authorization')}`"
  39. >
  40. <HttpAuthorization />
  41. </SmartTab>
  42. <SmartTab
  43. :id="'preRequestScript'"
  44. :label="`${$t('tab.pre_request_script')}`"
  45. >
  46. <HttpPreRequestScript />
  47. </SmartTab>
  48. <SmartTab :id="'tests'" :label="`${$t('tab.tests')}`">
  49. <HttpTests />
  50. </SmartTab>
  51. </SmartTabs>
  52. </Pane>
  53. <Pane
  54. :size="COLUMN_LAYOUT ? 65 : 50"
  55. class="flex flex-col hide-scrollbar !overflow-auto"
  56. >
  57. <HttpResponse ref="response" />
  58. </Pane>
  59. </Splitpanes>
  60. </Pane>
  61. <Pane
  62. v-if="SIDEBAR"
  63. size="25"
  64. min-size="20"
  65. class="hide-scrollbar !overflow-auto"
  66. >
  67. <SmartTabs styles="sticky bg-primary z-10 top-0" vertical>
  68. <SmartTab
  69. :id="'history'"
  70. icon="clock"
  71. :label="`${$t('tab.history')}`"
  72. :selected="true"
  73. >
  74. <History ref="historyComponent" :page="'rest'" />
  75. </SmartTab>
  76. <SmartTab
  77. :id="'collections'"
  78. icon="folder"
  79. :label="`${$t('tab.collections')}`"
  80. >
  81. <Collections />
  82. </SmartTab>
  83. <SmartTab
  84. :id="'env'"
  85. icon="layers"
  86. :label="`${$t('environment.title')}`"
  87. >
  88. <Environments />
  89. </SmartTab>
  90. </SmartTabs>
  91. </Pane>
  92. <SmartConfirmModal
  93. :show="confirmSync"
  94. :title="`${$t('confirm.sync')}`"
  95. @hide-modal="confirmSync = false"
  96. @resolve="syncRequest"
  97. />
  98. </Splitpanes>
  99. </template>
  100. <script lang="ts">
  101. import {
  102. defineComponent,
  103. onBeforeMount,
  104. onBeforeUnmount,
  105. onMounted,
  106. Ref,
  107. ref,
  108. useContext,
  109. } from "@nuxtjs/composition-api"
  110. import { Splitpanes, Pane } from "splitpanes"
  111. import "splitpanes/dist/splitpanes.css"
  112. import { map } from "rxjs/operators"
  113. import { Subscription } from "rxjs"
  114. import isEqual from "lodash/isEqual"
  115. import { HoppRESTRequest, HoppRESTAuthOAuth2 } from "@hoppscotch/data"
  116. import { useSetting } from "~/newstore/settings"
  117. import {
  118. restActiveParamsCount$,
  119. restActiveHeadersCount$,
  120. getRESTRequest,
  121. setRESTRequest,
  122. setRESTAuth,
  123. restAuth$,
  124. } from "~/newstore/RESTSession"
  125. import { translateExtURLParams } from "~/helpers/RESTExtURLParams"
  126. import {
  127. pluckRef,
  128. useReadonlyStream,
  129. useStream,
  130. } from "~/helpers/utils/composables"
  131. import { loadRequestFromSync, startRequestSync } from "~/helpers/fb/request"
  132. import { onLoggedIn } from "~/helpers/fb/auth"
  133. import { oauthRedirect } from "~/helpers/oauth"
  134. import useWindowSize from "~/helpers/utils/useWindowSize"
  135. function bindRequestToURLParams() {
  136. const { route } = useContext()
  137. // Get URL parameters and set that as the request
  138. onMounted(() => {
  139. const query = route.value.query
  140. // If query params are empty, or contains code or error param (these are from Oauth Redirect)
  141. // We skip URL params parsing
  142. if (Object.keys(query).length === 0 || query.code || query.error) return
  143. setRESTRequest(translateExtURLParams(query))
  144. })
  145. }
  146. function oAuthURL() {
  147. const auth = useStream(
  148. restAuth$,
  149. { authType: "none", authActive: true },
  150. setRESTAuth
  151. )
  152. const oauth2Token = pluckRef(auth as Ref<HoppRESTAuthOAuth2>, "token")
  153. onBeforeMount(async () => {
  154. const tokenInfo = await oauthRedirect()
  155. if (Object.prototype.hasOwnProperty.call(tokenInfo, "access_token")) {
  156. if (typeof tokenInfo === "object") {
  157. oauth2Token.value = tokenInfo.access_token
  158. }
  159. }
  160. })
  161. }
  162. function setupRequestSync(
  163. confirmSync: Ref<boolean>,
  164. requestForSync: Ref<HoppRESTRequest | null>
  165. ) {
  166. const { route } = useContext()
  167. // Subscription to request sync
  168. let sub: Subscription | null = null
  169. // Load request on login resolve and start sync
  170. onLoggedIn(async () => {
  171. if (
  172. Object.keys(route.value.query).length === 0 &&
  173. !(route.value.query.code || route.value.query.error)
  174. ) {
  175. const request = await loadRequestFromSync()
  176. if (request) {
  177. // setRESTRequest(request)
  178. if (!isEqual(request, getRESTRequest())) {
  179. requestForSync.value = request
  180. confirmSync.value = true
  181. }
  182. }
  183. }
  184. sub = startRequestSync()
  185. })
  186. // Stop subscripton to stop syncing
  187. onBeforeUnmount(() => {
  188. sub?.unsubscribe()
  189. })
  190. }
  191. export default defineComponent({
  192. components: { Splitpanes, Pane },
  193. setup() {
  194. const requestForSync = ref<HoppRESTRequest | null>(null)
  195. const confirmSync = ref(false)
  196. const syncRequest = () => {
  197. setRESTRequest(requestForSync.value!)
  198. }
  199. setupRequestSync(confirmSync, requestForSync)
  200. bindRequestToURLParams()
  201. return {
  202. windowInnerWidth: useWindowSize(),
  203. newActiveParamsCount$: useReadonlyStream(
  204. restActiveParamsCount$.pipe(
  205. map((e) => {
  206. if (e === 0) return null
  207. return `${e}`
  208. })
  209. ),
  210. null
  211. ),
  212. newActiveHeadersCount$: useReadonlyStream(
  213. restActiveHeadersCount$.pipe(
  214. map((e) => {
  215. if (e === 0) return null
  216. return `${e}`
  217. })
  218. ),
  219. null
  220. ),
  221. SIDEBAR: useSetting("SIDEBAR"),
  222. COLUMN_LAYOUT: useSetting("COLUMN_LAYOUT"),
  223. SIDEBAR_ON_LEFT: useSetting("SIDEBAR_ON_LEFT"),
  224. confirmSync,
  225. syncRequest,
  226. oAuthURL,
  227. requestForSync,
  228. }
  229. },
  230. })
  231. </script>