index.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <template>
  2. <div>
  3. <div class="sticky top-0 z-10 flex flex-col rounded-t bg-primary">
  4. <tippy ref="options" interactive trigger="click" theme="popover" arrow>
  5. <template #trigger>
  6. <span
  7. v-tippy="{ theme: 'tooltip' }"
  8. :title="`${t('environment.select')}`"
  9. class="flex-1 bg-transparent border-b border-dividerLight select-wrapper"
  10. >
  11. <ButtonSecondary
  12. v-if="selectedEnvironmentIndex !== -1"
  13. :label="environments[selectedEnvironmentIndex].name"
  14. class="flex-1 !justify-start pr-8 rounded-none"
  15. />
  16. <ButtonSecondary
  17. v-else
  18. :label="`${t('environment.select')}`"
  19. class="flex-1 !justify-start pr-8 rounded-none"
  20. />
  21. </span>
  22. </template>
  23. <div class="flex flex-col" role="menu">
  24. <SmartItem
  25. :label="`${t('environment.no_environment')}`"
  26. :info-icon="selectedEnvironmentIndex === -1 ? 'done' : ''"
  27. :active-info-icon="selectedEnvironmentIndex === -1"
  28. @click.native="
  29. () => {
  30. selectedEnvironmentIndex = -1
  31. options.tippy().hide()
  32. }
  33. "
  34. />
  35. <hr v-if="environments.length > 0" />
  36. <SmartItem
  37. v-for="(gen, index) in environments"
  38. :key="`gen-${index}`"
  39. :label="gen.name"
  40. :info-icon="index === selectedEnvironmentIndex ? 'done' : ''"
  41. :active-info-icon="index === selectedEnvironmentIndex"
  42. @click.native="
  43. () => {
  44. selectedEnvironmentIndex = index
  45. options.tippy().hide()
  46. }
  47. "
  48. />
  49. </div>
  50. </tippy>
  51. <div class="flex justify-between flex-1 border-b border-dividerLight">
  52. <ButtonSecondary
  53. svg="plus"
  54. :label="`${t('action.new')}`"
  55. class="!rounded-none"
  56. @click.native="displayModalAdd(true)"
  57. />
  58. <div class="flex">
  59. <ButtonSecondary
  60. v-tippy="{ theme: 'tooltip' }"
  61. to="https://docs.hoppscotch.io/features/environments"
  62. blank
  63. :title="t('app.wiki')"
  64. svg="help-circle"
  65. />
  66. <ButtonSecondary
  67. v-tippy="{ theme: 'tooltip' }"
  68. svg="archive"
  69. :title="t('modal.import_export')"
  70. @click.native="displayModalImportExport(true)"
  71. />
  72. </div>
  73. </div>
  74. </div>
  75. <div class="flex flex-col">
  76. <EnvironmentsEnvironment
  77. environment-index="Global"
  78. :environment="globalEnvironment"
  79. class="border-b border-dashed border-dividerLight"
  80. @edit-environment="editEnvironment('Global')"
  81. />
  82. <EnvironmentsEnvironment
  83. v-for="(environment, index) in environments"
  84. :key="`environment-${index}`"
  85. :environment-index="index"
  86. :environment="environment"
  87. @edit-environment="editEnvironment(index)"
  88. />
  89. </div>
  90. <div
  91. v-if="environments.length === 0"
  92. class="flex flex-col items-center justify-center p-4 text-secondaryLight"
  93. >
  94. <img
  95. :src="`/images/states/${$colorMode.value}/blockchain.svg`"
  96. loading="lazy"
  97. class="inline-flex flex-col object-contain object-center w-16 h-16 my-4"
  98. :alt="`${t('empty.environments')}`"
  99. />
  100. <span class="pb-4 text-center">
  101. {{ t("empty.environments") }}
  102. </span>
  103. <ButtonSecondary
  104. :label="`${t('add.new')}`"
  105. filled
  106. class="mb-4"
  107. @click.native="displayModalAdd(true)"
  108. />
  109. </div>
  110. <EnvironmentsDetails
  111. :show="showModalDetails"
  112. :action="action"
  113. :editing-environment-index="editingEnvironmentIndex"
  114. @hide-modal="displayModalEdit(false)"
  115. />
  116. <EnvironmentsImportExport
  117. :show="showModalImportExport"
  118. @hide-modal="displayModalImportExport(false)"
  119. />
  120. </div>
  121. </template>
  122. <script setup lang="ts">
  123. import { computed, ref } from "@nuxtjs/composition-api"
  124. import {
  125. useReadonlyStream,
  126. useStream,
  127. useI18n,
  128. } from "~/helpers/utils/composables"
  129. import {
  130. environments$,
  131. setCurrentEnvironment,
  132. selectedEnvIndex$,
  133. globalEnv$,
  134. } from "~/newstore/environments"
  135. const t = useI18n()
  136. const options = ref<any | null>(null)
  137. const globalEnv = useReadonlyStream(globalEnv$, [])
  138. const globalEnvironment = computed(() => ({
  139. name: "Global",
  140. variables: globalEnv.value,
  141. }))
  142. const environments = useReadonlyStream(environments$, [])
  143. const selectedEnvironmentIndex = useStream(
  144. selectedEnvIndex$,
  145. -1,
  146. setCurrentEnvironment
  147. )
  148. const showModalImportExport = ref(false)
  149. const showModalDetails = ref(false)
  150. const action = ref<"new" | "edit">("edit")
  151. const editingEnvironmentIndex = ref<number | "Global" | null>(null)
  152. const displayModalAdd = (shouldDisplay: boolean) => {
  153. action.value = "new"
  154. showModalDetails.value = shouldDisplay
  155. }
  156. const displayModalEdit = (shouldDisplay: boolean) => {
  157. action.value = "edit"
  158. showModalDetails.value = shouldDisplay
  159. if (!shouldDisplay) resetSelectedData()
  160. }
  161. const displayModalImportExport = (shouldDisplay: boolean) => {
  162. showModalImportExport.value = shouldDisplay
  163. }
  164. const editEnvironment = (environmentIndex: number | "Global") => {
  165. editingEnvironmentIndex.value = environmentIndex
  166. action.value = "edit"
  167. displayModalEdit(true)
  168. }
  169. const resetSelectedData = () => {
  170. editingEnvironmentIndex.value = null
  171. }
  172. </script>