Skip to content

Commit

Permalink
Use VMediaCollection for all search results
Browse files Browse the repository at this point in the history
Signed-off-by: Olga Bulat <obulat@gmail.com>
  • Loading branch information
obulat committed Mar 2, 2024
1 parent 6bb70dd commit 01c709c
Show file tree
Hide file tree
Showing 17 changed files with 526 additions and 342 deletions.
90 changes: 52 additions & 38 deletions frontend/src/components/VLoadMore.vue
Expand Up @@ -5,7 +5,7 @@
class="label-bold lg:description-bold h-16 w-full lg:h-18"
variant="filled-gray"
size="disabled"
:disabled="fetchState.isFetching"
:disabled="isFetching"
data-testid="load-more"
@click="onLoadMore"
>
Expand All @@ -14,7 +14,14 @@
</div>
</template>
<script lang="ts">
import { computed, defineComponent, onMounted, ref, watch } from "vue"
import {
computed,
defineComponent,
onMounted,
type PropType,
ref,
watch,
} from "vue"
import { storeToRefs } from "pinia"
import { useElementVisibility } from "@vueuse/core"
Expand All @@ -24,6 +31,10 @@ import { useAnalytics } from "~/composables/use-analytics"
import { useMediaStore } from "~/stores/media"
import { useSearchStore } from "~/stores/search"
import { useI18n } from "~/composables/use-i18n"
import { defineEvent } from "~/types/emits"
import type { ResultKind } from "~/types/result"
import type { SupportedSearchType } from "~/constants/media"
import VButton from "~/components/VButton.vue"
Expand All @@ -32,40 +43,46 @@ export default defineComponent({
components: {
VButton,
},
setup() {
props: {
searchType: {
type: String as PropType<SupportedSearchType>,
required: true,
},
searchTerm: {
type: String,
required: true,
},
kind: {
type: String as PropType<ResultKind>,
required: true,
},
isFetching: {
type: Boolean,
required: true,
},
},
emits: {
"load-more": defineEvent(),
},
setup(props, { emit }) {
const loadMoreSectionRef = ref(null)
const route = useRoute()
const i18n = useI18n()
const mediaStore = useMediaStore()
const searchStore = useSearchStore()
const { sendCustomEvent } = useAnalytics()
// Use the `_searchType` from mediaStore because it falls back to ALL_MEDIA
// for unsupported search types.
const { fetchState, resultCount, currentPage, _searchType } =
storeToRefs(mediaStore)
const { searchTerm } = storeToRefs(searchStore)
const searchStarted = computed(() => {
return searchStore.strategy === "default"
? searchTerm.value !== ""
: searchStore.collectionParams !== null
})
const { currentPage } = storeToRefs(mediaStore)
/**
* Whether we should show the "Load more" button.
* If the user has entered a search term, there is at least 1 page of results,
* there has been no fetching error, and there are more results to fetch,
* we show the button.
*/
const canLoadMore = computed(() => {
return Boolean(
searchStarted.value &&
!fetchState.value.fetchingError &&
!fetchState.value.isFinished &&
resultCount.value > 0
)
})
const canLoadMore = computed(
() => mediaStore.canLoadMore && searchStore.searchStarted
)
const reachResultEndEventSent = ref(false)
/**
Expand All @@ -75,37 +92,35 @@ export default defineComponent({
*
*/
const onLoadMore = async () => {
if (fetchState.value.isFetching) {
if (props.isFetching) {
return
}
reachResultEndEventSent.value = false
sendCustomEvent("LOAD_MORE_RESULTS", {
query: searchStore.searchTerm,
searchType: searchStore.searchType,
resultPage: currentPage.value || 1,
})
sendCustomEvent("LOAD_MORE_RESULTS", eventPayload.value)
await mediaStore.fetchMedia({
shouldPersistMedia: true,
})
emit("load-more")
}
const eventPayload = computed(() => {
return {
searchType: props.searchType,
query: props.searchTerm,
resultPage: currentPage.value || 1,
}
})
const sendReachResultEnd = () => {
// This function can be called before the media is fetched and
// currentPage is updated from 0, so we use the value or 1.
// The currentPage can never be 0 here because then the loadMore
// button would not be visible.
sendCustomEvent("REACH_RESULT_END", {
searchType: _searchType.value,
query: searchTerm.value,
resultPage: currentPage.value || 1,
})
sendCustomEvent("REACH_RESULT_END", eventPayload.value)
}
const buttonLabel = computed(() =>
fetchState.value.isFetching
props.isFetching
? i18n.t("browsePage.loading")
: i18n.t("browsePage.load")
)
Expand Down Expand Up @@ -136,7 +151,6 @@ export default defineComponent({
return {
buttonLabel,
fetchState,
onLoadMore,
canLoadMore,
Expand Down
147 changes: 147 additions & 0 deletions frontend/src/components/VLoadMoreOld.vue
@@ -0,0 +1,147 @@
<template>
<div ref="loadMoreSectionRef" class="w-full">
<VButton
v-show="canLoadMore"
class="label-bold lg:description-bold h-16 w-full lg:h-18"
variant="filled-gray"
size="disabled"
:disabled="fetchState.isFetching"
data-testid="load-more"
@click="onLoadMore"
>
{{ buttonLabel }}
</VButton>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, onMounted, ref, watch } from "vue"
import { storeToRefs } from "pinia"
import { useElementVisibility } from "@vueuse/core"
import { useRoute } from "@nuxtjs/composition-api"
import { useAnalytics } from "~/composables/use-analytics"
import { useMediaStore } from "~/stores/media"
import { useSearchStore } from "~/stores/search"
import { useI18n } from "~/composables/use-i18n"
import VButton from "~/components/VButton.vue"
export default defineComponent({
name: "VLoadMoreOld",
components: {
VButton,
},
setup() {
const loadMoreSectionRef = ref(null)
const route = useRoute()
const i18n = useI18n()
const mediaStore = useMediaStore()
const searchStore = useSearchStore()
const { sendCustomEvent } = useAnalytics()
// Use the `_searchType` from mediaStore because it falls back to ALL_MEDIA
// for unsupported search types.
const { fetchState, resultCount, currentPage, _searchType } =
storeToRefs(mediaStore)
const { searchTerm } = storeToRefs(searchStore)
const searchStarted = computed(() => {
return searchStore.strategy === "default"
? searchTerm.value !== ""
: searchStore.collectionParams !== null
})
/**
* Whether we should show the "Load more" button.
* If the user has entered a search term, there is at least 1 page of results,
* there has been no fetching error, and there are more results to fetch,
* we show the button.
*/
const canLoadMore = computed(() => {
return Boolean(
searchStarted.value &&
!fetchState.value.fetchingError &&
!fetchState.value.isFinished &&
resultCount.value > 0
)
})
const reachResultEndEventSent = ref(false)
/**
* On button click, fetch media, persisting the existing results.
* The button is disabled when we are fetching, but we still check
* whether we are currently fetching to be sure we don't fetch multiple times.
*
*/
const onLoadMore = async () => {
if (fetchState.value.isFetching) {
return
}
reachResultEndEventSent.value = false
sendCustomEvent("LOAD_MORE_RESULTS", {
query: searchStore.searchTerm,
searchType: searchStore.searchType,
resultPage: currentPage.value || 1,
})
await mediaStore.fetchMedia({
shouldPersistMedia: true,
})
}
const sendReachResultEnd = () => {
// This function can be called before the media is fetched and
// currentPage is updated from 0, so we use the value or 1.
// The currentPage can never be 0 here because then the loadMore
// button would not be visible.
sendCustomEvent("REACH_RESULT_END", {
searchType: _searchType.value,
query: searchTerm.value,
resultPage: currentPage.value || 1,
})
}
const buttonLabel = computed(() =>
fetchState.value.isFetching
? i18n.t("browsePage.loading")
: i18n.t("browsePage.load")
)
const mainPageElement = ref<HTMLElement | null>(null)
onMounted(() => {
mainPageElement.value = document.getElementById("main-page")
})
const isLoadMoreButtonVisible = useElementVisibility(loadMoreSectionRef, {
scrollTarget: mainPageElement,
})
// Reset the reachResultEndEvent whenever the route changes,
// to make sure the result end is tracked properly whenever
// the search query or content type changes
watch(route, () => {
reachResultEndEventSent.value = false
})
watch(isLoadMoreButtonVisible, (isVisible) => {
if (isVisible) {
if (reachResultEndEventSent.value) {
return
}
sendReachResultEnd()
reachResultEndEventSent.value = true
}
})
return {
buttonLabel,
fetchState,
onLoadMore,
canLoadMore,
loadMoreSectionRef,
}
},
})
</script>

0 comments on commit 01c709c

Please sign in to comment.