RawBody.vue 3.5 KB

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