CodegenModal.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <template>
  2. <SmartModal
  3. v-if="show"
  4. :title="`${t('request.generate_code')}`"
  5. @close="hideModal"
  6. >
  7. <template #body>
  8. <div class="flex flex-col px-2">
  9. <label for="requestType" class="px-4 pb-4">
  10. {{ $t("request.choose_language") }}
  11. </label>
  12. <tippy ref="options" interactive trigger="click" theme="popover" arrow>
  13. <template #trigger>
  14. <span class="select-wrapper">
  15. <ButtonSecondary
  16. :label="codegens.find((x) => x.id === codegenType).name"
  17. outline
  18. class="flex-1 pr-8"
  19. />
  20. </span>
  21. </template>
  22. <SmartItem
  23. v-for="(gen, index) in codegens"
  24. :key="`gen-${index}`"
  25. :label="gen.name"
  26. :info-icon="gen.id === codegenType ? 'done' : ''"
  27. :active-info-icon="gen.id === codegenType"
  28. @click.native="
  29. () => {
  30. codegenType = gen.id
  31. options.tippy().hide()
  32. }
  33. "
  34. />
  35. </tippy>
  36. <div class="flex flex-1 justify-between">
  37. <label for="generatedCode" class="p-4">
  38. {{ t("request.generated_code") }}
  39. </label>
  40. </div>
  41. <div
  42. v-if="codegenType"
  43. ref="generatedCode"
  44. class="border border-dividerLight rounded"
  45. ></div>
  46. </div>
  47. </template>
  48. <template #footer>
  49. <span class="flex">
  50. <ButtonPrimary
  51. :label="`${t('action.copy')}`"
  52. :svg="copyIcon"
  53. @click.native="copyRequestCode"
  54. />
  55. <ButtonSecondary
  56. :label="`${t('action.dismiss')}`"
  57. @click.native="hideModal"
  58. />
  59. </span>
  60. </template>
  61. </SmartModal>
  62. </template>
  63. <script setup lang="ts">
  64. import { computed, ref, useContext, watch } from "@nuxtjs/composition-api"
  65. import { codegens, generateCodegenContext } from "~/helpers/codegen/codegen"
  66. import { useCodemirror } from "~/helpers/editor/codemirror"
  67. import { copyToClipboard } from "~/helpers/utils/clipboard"
  68. import { getEffectiveRESTRequest } from "~/helpers/utils/EffectiveURL"
  69. import { getCurrentEnvironment } from "~/newstore/environments"
  70. import { getRESTRequest } from "~/newstore/RESTSession"
  71. const props = defineProps<{
  72. show: boolean
  73. }>()
  74. const emit = defineEmits<{
  75. (e: "hide-modal"): void
  76. }>()
  77. const {
  78. $toast,
  79. app: { i18n },
  80. } = useContext()
  81. const t = i18n.t.bind(i18n)
  82. const options = ref<any | null>(null)
  83. const request = ref(getRESTRequest())
  84. const codegenType = ref("curl")
  85. const copyIcon = ref("copy")
  86. const requestCode = computed(() => {
  87. const effectiveRequest = getEffectiveRESTRequest(
  88. request.value as any,
  89. getCurrentEnvironment()
  90. )
  91. return codegens
  92. .find((x) => x.id === codegenType.value)!
  93. .generator(generateCodegenContext(effectiveRequest))
  94. })
  95. const generatedCode = ref<any | null>(null)
  96. useCodemirror(generatedCode, requestCode, {
  97. extendedEditorConfig: {
  98. mode: "text/plain",
  99. readOnly: true,
  100. },
  101. linter: null,
  102. completer: null,
  103. })
  104. watch(
  105. () => props.show,
  106. (goingToShow) => {
  107. if (goingToShow) {
  108. request.value = getRESTRequest()
  109. }
  110. }
  111. )
  112. const hideModal = () => emit("hide-modal")
  113. const copyRequestCode = () => {
  114. copyToClipboard(requestCode.value)
  115. copyIcon.value = "check"
  116. $toast.success(`${t("state.copied_to_clipboard")}`, {
  117. icon: "content_paste",
  118. })
  119. setTimeout(() => (copyIcon.value = "copy"), 1000)
  120. }
  121. </script>