Parameters.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. <template>
  2. <AppSection label="parameters">
  3. <div
  4. class="
  5. bg-primary
  6. border-b border-dividerLight
  7. flex flex-1
  8. top-upperSecondaryStickyFold
  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("request.parameter_list") }}
  18. </label>
  19. <div class="flex">
  20. <ButtonSecondary
  21. v-tippy="{ theme: 'tooltip' }"
  22. to="https://docs.hoppscotch.io/features/parameters"
  23. blank
  24. :title="$t('app.wiki')"
  25. svg="help-circle"
  26. />
  27. <ButtonSecondary
  28. v-tippy="{ theme: 'tooltip' }"
  29. :title="$t('action.clear_all')"
  30. svg="trash-2"
  31. :disabled="bulkMode"
  32. @click.native="clearContent"
  33. />
  34. <ButtonSecondary
  35. v-tippy="{ theme: 'tooltip' }"
  36. :title="$t('state.bulk_mode')"
  37. svg="edit"
  38. :class="{ '!text-accent': bulkMode }"
  39. @click.native="bulkMode = !bulkMode"
  40. />
  41. <ButtonSecondary
  42. v-tippy="{ theme: 'tooltip' }"
  43. :title="$t('add.new')"
  44. svg="plus"
  45. :disabled="bulkMode"
  46. @click.native="addParam"
  47. />
  48. </div>
  49. </div>
  50. <div v-if="bulkMode" ref="bulkEditor"></div>
  51. <div v-else>
  52. <div
  53. v-for="(param, index) in params$"
  54. :key="`param-${index}`"
  55. class="divide-x divide-dividerLight border-b border-dividerLight flex"
  56. >
  57. <SmartEnvInput
  58. v-if="EXPERIMENTAL_URL_BAR_ENABLED"
  59. v-model="param.key"
  60. :placeholder="`${$t('count.parameter', { count: index + 1 })}`"
  61. styles="
  62. bg-transparent
  63. flex
  64. flex-1
  65. py-1
  66. px-4
  67. "
  68. @change="
  69. updateParam(index, {
  70. key: $event,
  71. value: param.value,
  72. active: param.active,
  73. })
  74. "
  75. />
  76. <input
  77. v-else
  78. class="bg-transparent flex flex-1 py-2 px-4"
  79. :placeholder="`${$t('count.parameter', {
  80. count: index + 1,
  81. })}`"
  82. :name="'param' + index"
  83. :value="param.key"
  84. autofocus
  85. @change="
  86. updateParam(index, {
  87. key: $event.target.value,
  88. value: param.value,
  89. active: param.active,
  90. })
  91. "
  92. />
  93. <SmartEnvInput
  94. v-if="EXPERIMENTAL_URL_BAR_ENABLED"
  95. v-model="param.value"
  96. :placeholder="`${$t('count.value', { count: index + 1 })}`"
  97. styles="
  98. bg-transparent
  99. flex
  100. flex-1
  101. py-1
  102. px-4
  103. "
  104. @change="
  105. updateParam(index, {
  106. key: param.key,
  107. value: $event,
  108. active: param.active,
  109. })
  110. "
  111. />
  112. <input
  113. v-else
  114. class="bg-transparent flex flex-1 py-2 px-4"
  115. :placeholder="`${$t('count.value', { count: index + 1 })}`"
  116. :name="'value' + index"
  117. :value="param.value"
  118. @change="
  119. updateParam(index, {
  120. key: param.key,
  121. value: $event.target.value,
  122. active: param.active,
  123. })
  124. "
  125. />
  126. <span>
  127. <ButtonSecondary
  128. v-tippy="{ theme: 'tooltip' }"
  129. :title="
  130. param.hasOwnProperty('active')
  131. ? param.active
  132. ? $t('action.turn_off')
  133. : $t('action.turn_on')
  134. : $t('action.turn_off')
  135. "
  136. :svg="
  137. param.hasOwnProperty('active')
  138. ? param.active
  139. ? 'check-circle'
  140. : 'circle'
  141. : 'check-circle'
  142. "
  143. color="green"
  144. @click.native="
  145. updateParam(index, {
  146. key: param.key,
  147. value: param.value,
  148. active: param.hasOwnProperty('active') ? !param.active : false,
  149. })
  150. "
  151. />
  152. </span>
  153. <span>
  154. <ButtonSecondary
  155. v-tippy="{ theme: 'tooltip' }"
  156. :title="$t('action.remove')"
  157. svg="trash"
  158. color="red"
  159. @click.native="deleteParam(index)"
  160. />
  161. </span>
  162. </div>
  163. <div
  164. v-if="params$.length === 0"
  165. class="
  166. flex flex-col
  167. text-secondaryLight
  168. p-4
  169. items-center
  170. justify-center
  171. "
  172. >
  173. <span class="text-center pb-4">
  174. {{ $t("empty.parameters") }}
  175. </span>
  176. <ButtonSecondary
  177. :label="`${$t('add.new')}`"
  178. svg="plus"
  179. filled
  180. @click.native="addParam"
  181. />
  182. </div>
  183. </div>
  184. </AppSection>
  185. </template>
  186. <script setup lang="ts">
  187. import { ref, useContext, watch } from "@nuxtjs/composition-api"
  188. import { useCodemirror } from "~/helpers/editor/codemirror"
  189. import { HoppRESTParam } from "~/helpers/types/HoppRESTRequest"
  190. import { useReadonlyStream } from "~/helpers/utils/composables"
  191. import {
  192. restParams$,
  193. addRESTParam,
  194. updateRESTParam,
  195. deleteRESTParam,
  196. deleteAllRESTParams,
  197. setRESTParams,
  198. } from "~/newstore/RESTSession"
  199. import { useSetting } from "~/newstore/settings"
  200. import "codemirror/mode/yaml/yaml"
  201. const {
  202. $toast,
  203. app: { i18n },
  204. } = useContext()
  205. const t = i18n.t.bind(i18n)
  206. const bulkMode = ref(false)
  207. const bulkParams = ref("")
  208. watch(bulkParams, () => {
  209. try {
  210. const transformation = bulkParams.value.split("\n").map((item) => ({
  211. key: item.substring(0, item.indexOf(":")).trim().replace(/^\/\//, ""),
  212. value: item.substring(item.indexOf(":") + 1).trim(),
  213. active: !item.trim().startsWith("//"),
  214. }))
  215. setRESTParams(transformation)
  216. } catch (e) {
  217. $toast.error(`${t("error.something_went_wrong")}`, {
  218. icon: "error_outline",
  219. })
  220. console.error(e)
  221. }
  222. })
  223. const bulkEditor = ref<any | null>(null)
  224. useCodemirror(bulkEditor, bulkParams, {
  225. extendedEditorConfig: {
  226. mode: "text/x-yaml",
  227. placeholder: `${t("state.bulk_mode_placeholder")}`,
  228. },
  229. linter: null,
  230. completer: null,
  231. })
  232. const params$ = useReadonlyStream(restParams$, [])
  233. watch(
  234. params$,
  235. (newValue) => {
  236. if (
  237. (newValue[newValue.length - 1]?.key !== "" ||
  238. newValue[newValue.length - 1]?.value !== "") &&
  239. newValue.length
  240. )
  241. addParam()
  242. },
  243. { deep: true }
  244. )
  245. const addParam = () => {
  246. addRESTParam({ key: "", value: "", active: true })
  247. }
  248. const updateParam = (index: number, item: HoppRESTParam) => {
  249. updateRESTParam(index, item)
  250. }
  251. const deleteParam = (index: number) => {
  252. deleteRESTParam(index)
  253. }
  254. const clearContent = () => {
  255. deleteAllRESTParams()
  256. }
  257. const EXPERIMENTAL_URL_BAR_ENABLED = useSetting("EXPERIMENTAL_URL_BAR_ENABLED")
  258. </script>