index.vue 7.5 KB

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