JSONLensRenderer.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <template>
  2. <div>
  3. <div
  4. class="
  5. bg-primary
  6. border-b border-dividerLight
  7. flex flex-1
  8. top-lowerSecondaryStickyFold
  9. pl-4
  10. z-10
  11. sticky
  12. items-center
  13. justify-between
  14. "
  15. >
  16. <label class="font-semibold text-secondaryLight">
  17. {{ $t("response.body") }}
  18. </label>
  19. <div class="flex">
  20. <ButtonSecondary
  21. v-if="response.body"
  22. ref="downloadResponse"
  23. v-tippy="{ theme: 'tooltip' }"
  24. :title="$t('action.download_file')"
  25. :svg="downloadIcon"
  26. @click.native="downloadResponse"
  27. />
  28. <ButtonSecondary
  29. v-if="response.body"
  30. ref="copyResponse"
  31. v-tippy="{ theme: 'tooltip' }"
  32. :title="$t('action.copy')"
  33. :svg="copyIcon"
  34. @click.native="copyResponse"
  35. />
  36. </div>
  37. </div>
  38. <div class="relative">
  39. <SmartAceEditor
  40. :value="jsonBodyText"
  41. :lang="'json'"
  42. :provide-outline="true"
  43. :options="{
  44. maxLines: Infinity,
  45. minLines: 16,
  46. autoScrollEditorIntoView: true,
  47. readOnly: true,
  48. showPrintMargin: false,
  49. useWorker: false,
  50. }"
  51. styles="border-b border-dividerLight"
  52. />
  53. </div>
  54. </div>
  55. </template>
  56. <script>
  57. import { defineComponent } from "@nuxtjs/composition-api"
  58. import TextContentRendererMixin from "./mixins/TextContentRendererMixin"
  59. import { copyToClipboard } from "~/helpers/utils/clipboard"
  60. export default defineComponent({
  61. mixins: [TextContentRendererMixin],
  62. props: {
  63. response: { type: Object, default: () => {} },
  64. },
  65. data() {
  66. return {
  67. downloadIcon: "download",
  68. copyIcon: "copy",
  69. }
  70. },
  71. computed: {
  72. jsonBodyText() {
  73. try {
  74. return JSON.stringify(JSON.parse(this.responseBodyText), null, 2)
  75. } catch (e) {
  76. // Most probs invalid JSON was returned, so drop prettification (should we warn ?)
  77. return this.responseBodyText
  78. }
  79. },
  80. responseType() {
  81. return (
  82. this.response.headers.find(
  83. (h) => h.key.toLowerCase() === "content-type"
  84. ).value || ""
  85. )
  86. .split(";")[0]
  87. .toLowerCase()
  88. },
  89. },
  90. methods: {
  91. downloadResponse() {
  92. const dataToWrite = this.responseBodyText
  93. const file = new Blob([dataToWrite], { type: "application/json" })
  94. const a = document.createElement("a")
  95. const url = URL.createObjectURL(file)
  96. a.href = url
  97. // TODO get uri from meta
  98. a.download = `${url.split("/").pop().split("#")[0].split("?")[0]}`
  99. document.body.appendChild(a)
  100. a.click()
  101. this.downloadIcon = "check"
  102. this.$toast.success(this.$t("state.download_started"), {
  103. icon: "downloading",
  104. })
  105. setTimeout(() => {
  106. document.body.removeChild(a)
  107. URL.revokeObjectURL(url)
  108. this.downloadIcon = "download"
  109. }, 1000)
  110. },
  111. copyResponse() {
  112. copyToClipboard(this.responseBodyText)
  113. this.copyIcon = "check"
  114. this.$toast.success(this.$t("state.copied_to_clipboard"), {
  115. icon: "content_paste",
  116. })
  117. setTimeout(() => (this.copyIcon = "copy"), 1000)
  118. },
  119. },
  120. })
  121. </script>