From 56a3e9924e1934518fafe8819327243bc901221f Mon Sep 17 00:00:00 2001 From: Olga Bulat Date: Tue, 27 Feb 2024 13:29:55 +0300 Subject: [PATCH 1/9] Use `VMediaCollection` for all search results Signed-off-by: Olga Bulat --- frontend/src/components/VLoadMore.vue | 89 ++++++----- frontend/src/components/VLoadMoreOld.vue | 147 ++++++++++++++++++ .../VSearchResultsGrid/VAllResultsGrid.vue | 121 +++----------- .../VSearchResultsGrid/VAudioList.vue | 6 +- .../VSearchResultsGrid/VCollectionResults.vue | 71 +++++++++ .../VSearchResultsGrid/VImageGrid.vue | 6 +- .../VSearchResultsGrid/VMediaCollection.vue | 19 ++- .../VSearchResultsGrid/VSearchResults.vue | 112 +++++++++++++ frontend/src/middleware/search.ts | 2 +- frontend/src/pages/search.vue | 81 +++++----- frontend/src/pages/search/audio.vue | 40 ++--- frontend/src/pages/search/image.vue | 25 ++- frontend/src/pages/search/index.vue | 29 +++- frontend/src/stores/media/index.ts | 18 ++- frontend/src/stores/search.ts | 5 + .../specs/components/v-image-grid.spec.js | 37 ----- .../test/unit/specs/pages/browse-page.spec.js | 63 -------- 17 files changed, 529 insertions(+), 342 deletions(-) create mode 100644 frontend/src/components/VLoadMoreOld.vue create mode 100644 frontend/src/components/VSearchResultsGrid/VCollectionResults.vue create mode 100644 frontend/src/components/VSearchResultsGrid/VSearchResults.vue delete mode 100644 frontend/test/unit/specs/components/v-image-grid.spec.js delete mode 100644 frontend/test/unit/specs/pages/browse-page.spec.js diff --git a/frontend/src/components/VLoadMore.vue b/frontend/src/components/VLoadMore.vue index 2d17512136..a6e0c9bbc5 100644 --- a/frontend/src/components/VLoadMore.vue +++ b/frontend/src/components/VLoadMore.vue @@ -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" > @@ -14,7 +14,14 @@ diff --git a/frontend/src/components/VSearchResultsGrid/VAllResultsGrid.vue b/frontend/src/components/VSearchResultsGrid/VAllResultsGrid.vue index 23f0caf8e8..b4485f86f6 100644 --- a/frontend/src/components/VSearchResultsGrid/VAllResultsGrid.vue +++ b/frontend/src/components/VSearchResultsGrid/VAllResultsGrid.vue @@ -1,42 +1,16 @@ @@ -38,12 +38,12 @@ import type { ImageDetail } from "~/types/media" import type { ResultKind } from "~/types/result" import VGridSkeleton from "~/components/VSkeleton/VGridSkeleton.vue" -import VLoadMore from "~/components/VLoadMore.vue" +import VLoadMoreOld from "~/components/VLoadMoreOld.vue" import VImageCell from "~/components/VImageCell/VImageCell.vue" export default defineComponent({ name: "ImageGrid", - components: { VGridSkeleton, VLoadMore, VImageCell }, + components: { VGridSkeleton, VLoadMoreOld, VImageCell }, props: { results: { type: Array as PropType, diff --git a/frontend/src/components/VSearchResultsGrid/VMediaCollection.vue b/frontend/src/components/VSearchResultsGrid/VMediaCollection.vue index 062e1639a0..df7f2a0447 100644 --- a/frontend/src/components/VSearchResultsGrid/VMediaCollection.vue +++ b/frontend/src/components/VSearchResultsGrid/VMediaCollection.vue @@ -15,7 +15,7 @@ :class="{ 'pt-2 sm:pt-0': results.type === 'image' }" /> - + import { computed, defineComponent, inject, type PropType, ref } from "vue" -import { IsSidebarVisibleKey, ShowScrollButtonKey } from "~/types/provides" import type { Results } from "~/types/result" - +import { IsSidebarVisibleKey, ShowScrollButtonKey } from "~/types/provides" import { defineEvent } from "~/types/emits" +import { useMediaStore } from "~/stores/media" import VGridSkeleton from "~/components/VSkeleton/VGridSkeleton.vue" import VAllResultsGrid from "~/components/VSearchResultsGrid/VAllResultsGrid.vue" @@ -68,9 +68,12 @@ export default defineComponent({ type: String as PropType, default: null, }, + /** + * Overrides the value from the media store. + * Used for the related media which uses a different store. + */ isFetching: { type: Boolean, - required: true, }, }, emits: { @@ -80,8 +83,13 @@ export default defineComponent({ const showScrollButton = inject(ShowScrollButtonKey, ref(false)) const isSidebarVisible = inject(IsSidebarVisibleKey, ref(false)) + const mediaStore = useMediaStore() + const _isFetching = computed( + () => props.isFetching ?? mediaStore.fetchState.isFetching + ) + const showSkeleton = computed(() => { - return props.isFetching && props.results.items.length === 0 + return _isFetching.value && props.results.items.length === 0 }) const component = computed(() => { @@ -98,6 +106,7 @@ export default defineComponent({ showSkeleton, showScrollButton, isSidebarVisible, + _isFetching, component, } }, diff --git a/frontend/src/components/VSearchResultsGrid/VSearchResults.vue b/frontend/src/components/VSearchResultsGrid/VSearchResults.vue new file mode 100644 index 0000000000..d7f7e63282 --- /dev/null +++ b/frontend/src/components/VSearchResultsGrid/VSearchResults.vue @@ -0,0 +1,112 @@ + + diff --git a/frontend/src/middleware/search.ts b/frontend/src/middleware/search.ts index ba337051ee..4a100a678e 100644 --- a/frontend/src/middleware/search.ts +++ b/frontend/src/middleware/search.ts @@ -47,7 +47,7 @@ export const searchMiddleware: Middleware = async ({ const results = await mediaStore.fetchMedia() const fetchingError = mediaStore.fetchState.fetchingError - if (!results && fetchingError && !handledClientSide(fetchingError)) { + if (!results.length && fetchingError && !handledClientSide(fetchingError)) { nuxtError(fetchingError) } } diff --git a/frontend/src/pages/search.vue b/frontend/src/pages/search.vue index b95cb25f87..4a4c8da475 100644 --- a/frontend/src/pages/search.vue +++ b/frontend/src/pages/search.vue @@ -10,39 +10,21 @@ class="w-full py-10" />
-
- {{ - searchTerm - }} -
- -
diff --git a/frontend/src/pages/search/image.vue b/frontend/src/pages/search/image.vue index 68db335091..bdb0dddd79 100644 --- a/frontend/src/pages/search/image.vue +++ b/frontend/src/pages/search/image.vue @@ -1,38 +1,35 @@ diff --git a/frontend/src/pages/search/index.vue b/frontend/src/pages/search/index.vue index 079473bc73..9be8d4eff8 100644 --- a/frontend/src/pages/search/index.vue +++ b/frontend/src/pages/search/index.vue @@ -1,14 +1,35 @@ diff --git a/frontend/src/stores/media/index.ts b/frontend/src/stores/media/index.ts index 71c37fac05..959e14fe45 100644 --- a/frontend/src/stores/media/index.ts +++ b/frontend/src/stores/media/index.ts @@ -286,6 +286,14 @@ export const useMediaStore = defineStore("media", { !this.mediaFetchState[type].isFinished ) }, + + canLoadMore(): boolean { + return ( + !this.fetchState.fetchingError && + !this.fetchState.isFinished && + this.resultCount > 0 + ) + }, }, actions: { @@ -414,20 +422,20 @@ export const useMediaStore = defineStore("media", { const mediaToFetch = this._fetchableMediaTypes - const resultCounts = await Promise.all( + await Promise.allSettled( mediaToFetch.map((mediaType) => this.fetchSingleMediaType({ mediaType, shouldPersistMedia }) ) ) - const resultCount = resultCounts.includes(null) - ? null - : (resultCounts as number[]).reduce((a, b) => a + b, 0) this.currentPage = mediaType === ALL_MEDIA ? this.currentPage + 1 : this.results[mediaType].page - return resultCount + + return mediaType === ALL_MEDIA + ? this.allMedia + : this.resultItems[mediaType] }, clearMedia() { diff --git a/frontend/src/stores/search.ts b/frontend/src/stores/search.ts index 8ac22e8f21..737ed12c9c 100644 --- a/frontend/src/stores/search.ts +++ b/frontend/src/stores/search.ts @@ -149,6 +149,11 @@ export const useSearchStore = defineStore("search", { state.recentSearches = useStorage("recent-searches", []) }, getters: { + searchStarted(state) { + return state.strategy === "default" + ? state.searchTerm.length > 0 + : state.collectionParams !== null + }, filterCategories(state) { return Object.keys(state.filters) as FilterCategory[] }, diff --git a/frontend/test/unit/specs/components/v-image-grid.spec.js b/frontend/test/unit/specs/components/v-image-grid.spec.js deleted file mode 100644 index fb2ad0d730..0000000000 --- a/frontend/test/unit/specs/components/v-image-grid.spec.js +++ /dev/null @@ -1,37 +0,0 @@ -import { screen } from "@testing-library/vue" - -import { render } from "~~/test/unit/test-utils/render" - -import VImageGrid from "~/components/VSearchResultsGrid/VImageGrid.vue" - -const propsData = { - results: [ - { id: "i1", url: "http://localhost:8080/i1.png", title: "image1" }, - { id: "i2", url: "http://localhost:8080/i2.jpg", title: "image2" }, - { id: "i3", url: "http://localhost:8080/i3.svg", title: "image3" }, - ], - fetchState: { - isSinglePage: true, - isFetching: false, - fetchingError: null, - }, - kind: "related", - imageGridLabel: "Image Results", -} - -describe("VImageGrid", () => { - let options - beforeEach(() => { - options = { - props: propsData, - stubs: ["VLicense"], - } - }) - it("renders images without load more button for related images", () => { - const imageCount = propsData.results.length - render(VImageGrid, options) - expect(screen.queryAllByRole("img").length).toEqual(imageCount) - expect(screen.queryAllByRole("figure").length).toEqual(imageCount) - expect(screen.queryByTestId("load-more")).toBeNull() - }) -}) diff --git a/frontend/test/unit/specs/pages/browse-page.spec.js b/frontend/test/unit/specs/pages/browse-page.spec.js deleted file mode 100644 index 409ae111be..0000000000 --- a/frontend/test/unit/specs/pages/browse-page.spec.js +++ /dev/null @@ -1,63 +0,0 @@ -import { screen } from "@testing-library/vue" -import { ref } from "vue" - -import { render } from "~~/test/unit/test-utils/render" - -import { IMAGE } from "~/constants/media" -import { useSearchStore } from "~/stores/search" - -import SearchIndex from "~/pages/search.vue" - -import { - IsHeaderScrolledKey, - IsSidebarVisibleKey, - ShowScrollButtonKey, -} from "~/types/provides" - -describe("SearchIndex", () => { - let options - const defaultProvideOptions = { - showScrollButton: ref(false), - [IsHeaderScrolledKey]: ref(false), - [IsSidebarVisibleKey]: ref(false), - [ShowScrollButtonKey]: ref(false), - } - let searchStore - - beforeEach(() => { - options = { - provide: defaultProvideOptions, - mocks: { - $router: { path: { name: "search-image" } }, - $route: { path: "/search/image" }, - }, - stubs: { - NuxtChild: true, - VSearchGrid: true, - }, - } - }) - - it("hides the scroll button when injected value is false", () => { - options.provide.showScrollButton.value = false - - render(SearchIndex, options, (localVue, options) => { - searchStore = useSearchStore(options.pinia) - searchStore.setSearchTerm("cat") - searchStore.setSearchType(IMAGE) - }) - - expect(screen.queryByLabelText(/scroll/i)).not.toBeVisible() - }) - - it("shows the scroll button when injected value is true", () => { - options.provide[ShowScrollButtonKey].value = true - render(SearchIndex, options, (localVue, options) => { - searchStore = useSearchStore(options.pinia) - searchStore.setSearchTerm("cat") - searchStore.setSearchType(IMAGE) - }) - - expect(screen.queryByLabelText(/scroll/i)).toBeVisible() - }) -}) From 77ea5234c2cb3b789c9d08b833836ad1b76e1829 Mon Sep 17 00:00:00 2001 From: Olga Bulat Date: Thu, 7 Mar 2024 18:59:04 +0300 Subject: [PATCH 2/9] Make isFetching a prop Signed-off-by: Olga Bulat --- .../VSearchResultsGrid/VCollectionResults.vue | 7 ++++++- .../VSearchResultsGrid/VMediaCollection.vue | 12 +++--------- .../components/VSearchResultsGrid/VSearchResults.vue | 7 ++++++- frontend/src/pages/search.vue | 3 +++ frontend/src/pages/search/audio.vue | 7 ++++++- frontend/src/pages/search/image.vue | 7 ++++++- frontend/src/pages/search/index.vue | 5 +++++ 7 files changed, 35 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/VSearchResultsGrid/VCollectionResults.vue b/frontend/src/components/VSearchResultsGrid/VCollectionResults.vue index 1aa4e2c5a3..40b66f70fa 100644 --- a/frontend/src/components/VSearchResultsGrid/VCollectionResults.vue +++ b/frontend/src/components/VSearchResultsGrid/VCollectionResults.vue @@ -1,6 +1,7 @@ -