Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the VMediaCollection for search and collection results #3835

Merged
merged 9 commits into from Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
110 changes: 0 additions & 110 deletions frontend/src/components/VCollectionPage.vue

This file was deleted.

104 changes: 57 additions & 47 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,16 +14,25 @@
</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"

import { useRoute } from "@nuxtjs/composition-api"
import { useContext, 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 { 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,80 +41,82 @@ 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 { $sendCustomEvent } = useContext()

const { currentPage } = storeToRefs(mediaStore)

const eventPayload = computed(() => {
return {
searchType: props.searchType,
query: props.searchTerm,
resultPage: currentPage.value || 1,
}
})

/**
* 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.
* If the fetching for the current query has started, 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)

const reachResultEndEventSent = ref(false)
/**
* On button click, fetch media, persisting the existing results.
* On button click, send the analytics events and emit `load-more` event.
*
* 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) {
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 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 +147,6 @@ export default defineComponent({

return {
buttonLabel,
fetchState,
onLoadMore,
canLoadMore,

Expand Down