index.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <template>
  2. <AppSection label="history">
  3. <div class="bg-primary border-b border-dividerLight flex top-0 z-10 sticky">
  4. <input
  5. v-model="filterText"
  6. type="search"
  7. autocomplete="off"
  8. class="bg-transparent flex w-full p-4 py-2"
  9. :placeholder="`${$t('action.search')}`"
  10. />
  11. <div class="flex">
  12. <ButtonSecondary
  13. v-tippy="{ theme: 'tooltip' }"
  14. to="https://docs.hoppscotch.io/features/history"
  15. blank
  16. :title="$t('app.wiki')"
  17. svg="help-circle"
  18. />
  19. <ButtonSecondary
  20. v-tippy="{ theme: 'tooltip' }"
  21. data-testid="clear_history"
  22. :disabled="history.length === 0"
  23. svg="trash-2"
  24. :title="$t('action.clear_all')"
  25. @click.native="confirmRemove = true"
  26. />
  27. </div>
  28. </div>
  29. <div class="flex flex-col">
  30. <div v-for="(entry, index) in filteredHistory" :key="`entry-${index}`">
  31. <HistoryRestCard
  32. v-if="page == 'rest'"
  33. :id="index"
  34. :entry="entry"
  35. :show-more="showMore"
  36. @toggle-star="toggleStar(entry)"
  37. @delete-entry="deleteHistory(entry)"
  38. @use-entry="useHistory(entry)"
  39. />
  40. <HistoryGraphqlCard
  41. v-if="page == 'graphql'"
  42. :entry="entry"
  43. :show-more="showMore"
  44. @toggle-star="toggleStar(entry)"
  45. @delete-entry="deleteHistory(entry)"
  46. @use-entry="useHistory(entry)"
  47. />
  48. </div>
  49. </div>
  50. <div
  51. v-if="!(filteredHistory.length !== 0 || history.length === 0)"
  52. class="flex flex-col text-secondaryLight p-4 items-center justify-center"
  53. >
  54. <i class="opacity-75 pb-2 material-icons">manage_search</i>
  55. <span class="text-center">
  56. {{ $t("state.nothing_found") }} "{{ filterText }}"
  57. </span>
  58. </div>
  59. <div
  60. v-if="history.length === 0"
  61. class="flex flex-col text-secondaryLight p-4 items-center justify-center"
  62. >
  63. <img
  64. :src="`/images/states/${$colorMode.value}/history.svg`"
  65. loading="lazy"
  66. class="flex-col object-contain object-center h-16 my-4 w-16 inline-flex"
  67. :alt="$t('empty.history')"
  68. />
  69. <span class="text-center mb-4">
  70. {{ $t("empty.history") }}
  71. </span>
  72. </div>
  73. <SmartConfirmModal
  74. :show="confirmRemove"
  75. :title="`${$t('confirm.remove_history')}`"
  76. @hide-modal="confirmRemove = false"
  77. @resolve="clearHistory"
  78. />
  79. </AppSection>
  80. </template>
  81. <script lang="ts">
  82. import { defineComponent, PropType } from "@nuxtjs/composition-api"
  83. import { useReadonlyStream } from "~/helpers/utils/composables"
  84. import {
  85. restHistory$,
  86. graphqlHistory$,
  87. clearRESTHistory,
  88. clearGraphqlHistory,
  89. toggleGraphqlHistoryEntryStar,
  90. toggleRESTHistoryEntryStar,
  91. deleteGraphqlHistoryEntry,
  92. deleteRESTHistoryEntry,
  93. RESTHistoryEntry,
  94. GQLHistoryEntry,
  95. } from "~/newstore/history"
  96. import { setRESTRequest } from "~/newstore/RESTSession"
  97. export default defineComponent({
  98. props: {
  99. page: { type: String as PropType<"rest" | "graphql">, default: null },
  100. },
  101. setup(props) {
  102. return {
  103. history: useReadonlyStream<RESTHistoryEntry[] | GQLHistoryEntry[]>(
  104. props.page === "rest" ? restHistory$ : graphqlHistory$,
  105. []
  106. ),
  107. }
  108. },
  109. data() {
  110. return {
  111. filterText: "",
  112. showMore: false,
  113. confirmRemove: false,
  114. }
  115. },
  116. computed: {
  117. filteredHistory(): any[] {
  118. const filteringHistory = this.history as Array<
  119. RESTHistoryEntry | GQLHistoryEntry
  120. >
  121. return filteringHistory.filter(
  122. (entry: RESTHistoryEntry | GQLHistoryEntry) => {
  123. const filterText = this.filterText.toLowerCase()
  124. return Object.keys(entry).some((key) => {
  125. let value = entry[key as keyof typeof entry]
  126. if (value) {
  127. value = `${value}`
  128. return value.toLowerCase().includes(filterText)
  129. }
  130. return false
  131. })
  132. }
  133. )
  134. },
  135. },
  136. methods: {
  137. clearHistory() {
  138. if (this.page === "rest") clearRESTHistory()
  139. else clearGraphqlHistory()
  140. this.$toast.success(`${this.$t("state.history_deleted")}`)
  141. },
  142. useHistory(entry: any) {
  143. if (this.page === "rest") setRESTRequest(entry.request)
  144. },
  145. deleteHistory(entry: any) {
  146. if (this.page === "rest") deleteRESTHistoryEntry(entry)
  147. else deleteGraphqlHistoryEntry(entry)
  148. this.$toast.success(`${this.$t("state.deleted")}`)
  149. },
  150. toggleStar(entry: any) {
  151. if (this.page === "rest") toggleRESTHistoryEntryStar(entry)
  152. else toggleGraphqlHistoryEntryStar(entry)
  153. },
  154. },
  155. })
  156. </script>