RawBody.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. <template>
  2. <div>
  3. <div
  4. class="bg-primary border-b border-dividerLight flex flex-1 top-upperTertiaryStickyFold pl-4 z-10 sticky items-center justify-between"
  5. >
  6. <label class="font-semibold text-secondaryLight">
  7. {{ t("request.raw_body") }}
  8. </label>
  9. <div class="flex">
  10. <ButtonSecondary
  11. v-tippy="{ theme: 'tooltip' }"
  12. to="https://docs.hoppscotch.io/features/body"
  13. blank
  14. :title="t('app.wiki')"
  15. svg="help-circle"
  16. />
  17. <ButtonSecondary
  18. v-tippy="{ theme: 'tooltip' }"
  19. :title="t('state.linewrap')"
  20. :class="{ '!text-accent': linewrapEnabled }"
  21. svg="wrap-text"
  22. @click.native.prevent="linewrapEnabled = !linewrapEnabled"
  23. />
  24. <ButtonSecondary
  25. v-tippy="{ theme: 'tooltip' }"
  26. :title="t('action.clear')"
  27. svg="trash-2"
  28. @click.native="clearContent"
  29. />
  30. <ButtonSecondary
  31. v-if="contentType && contentType.endsWith('json')"
  32. ref="prettifyRequest"
  33. v-tippy="{ theme: 'tooltip' }"
  34. :title="t('action.prettify')"
  35. :svg="prettifyIcon"
  36. @click.native="prettifyRequestBody"
  37. />
  38. <label for="payload">
  39. <ButtonSecondary
  40. v-tippy="{ theme: 'tooltip' }"
  41. :title="t('import.json')"
  42. svg="file-plus"
  43. @click.native="$refs.payload.click()"
  44. />
  45. </label>
  46. <input
  47. ref="payload"
  48. class="input"
  49. name="payload"
  50. type="file"
  51. @change="uploadPayload"
  52. />
  53. </div>
  54. </div>
  55. <div ref="rawBodyParameters"></div>
  56. </div>
  57. </template>
  58. <script setup lang="ts">
  59. import { computed, reactive, ref } from "@nuxtjs/composition-api"
  60. import { useCodemirror } from "~/helpers/editor/codemirror"
  61. import { getEditorLangForMimeType } from "~/helpers/editorutils"
  62. import { pluckRef, useI18n, useToast } from "~/helpers/utils/composables"
  63. import { useRESTRequestBody } from "~/newstore/RESTSession"
  64. const t = useI18n()
  65. const props = defineProps<{
  66. contentType: string
  67. }>()
  68. const toast = useToast()
  69. const rawParamsBody = pluckRef(useRESTRequestBody(), "body")
  70. const prettifyIcon = ref("wand")
  71. const rawInputEditorLang = computed(() =>
  72. getEditorLangForMimeType(props.contentType)
  73. )
  74. const linewrapEnabled = ref(true)
  75. const rawBodyParameters = ref<any | null>(null)
  76. useCodemirror(
  77. rawBodyParameters,
  78. rawParamsBody,
  79. reactive({
  80. extendedEditorConfig: {
  81. lineWrapping: linewrapEnabled,
  82. mode: rawInputEditorLang,
  83. placeholder: t("request.raw_body"),
  84. },
  85. linter: null,
  86. completer: null,
  87. })
  88. )
  89. const clearContent = () => {
  90. rawParamsBody.value = ""
  91. }
  92. const uploadPayload = (e: InputEvent) => {
  93. const file = e.target.files[0]
  94. if (file !== undefined && file !== null) {
  95. const reader = new FileReader()
  96. reader.onload = ({ target }) => {
  97. rawParamsBody.value = target?.result
  98. }
  99. reader.readAsText(file)
  100. toast.success(`${t("state.file_imported")}`)
  101. } else {
  102. toast.error(`${t("action.choose_file")}`)
  103. }
  104. }
  105. const prettifyRequestBody = () => {
  106. try {
  107. const jsonObj = JSON.parse(rawParamsBody.value)
  108. rawParamsBody.value = JSON.stringify(jsonObj, null, 2)
  109. prettifyIcon.value = "check"
  110. setTimeout(() => (prettifyIcon.value = "wand"), 1000)
  111. } catch (e) {
  112. console.error(e)
  113. toast.error(`${t("error.json_prettify_invalid_body")}`)
  114. }
  115. }
  116. </script>