diff --git a/src/modules/search/pages/Search.vue b/src/modules/search/pages/Search.vue index e1c64487c82746a3374cf3f42cd5dee623445ccf..fa662c2f7d672d4d3d82fedca796a01e1247ae2b 100644 --- a/src/modules/search/pages/Search.vue +++ b/src/modules/search/pages/Search.vue @@ -28,7 +28,7 @@ <b-form-select v-model="selectedProject" :options="allProjectsOptions" - @change="queryData(searchText)" + @change="queryData(searchText, selectedPage, paginationPageSize)" > <template #first> <b-form-select-option :value="null"> @@ -41,7 +41,7 @@ <b-form-select v-model="selectedResource" :options="projectResourcesOptions" - @change="queryData(searchText)" + @change="queryData(searchText, selectedPage, paginationPageSize)" > <template #first> <b-form-select-option :value="null"> @@ -56,7 +56,7 @@ id="searchButton" variant="primary" :disabled="resultsViewLoading" - @click="queryData(searchText)" + @click="queryData(searchText, selectedPage, paginationPageSize)" > {{ $t("page.search.search") }} <b-spinner v-if="resultsViewLoading" variant="secondary" /> @@ -132,10 +132,10 @@ </template> <b-table id="resultsView" - :items="filteredResults" + :items="searchResults" :fields="resultsViewFields" - :per-page="paginationPerPage" - :current-page="paginationCurrentPage" + :per-page="pagination ? pagination.PageSize : 0" + :current-page="1" thead-class="d-none" style="min-height: 100%" small @@ -161,9 +161,7 @@ <!-- Show footer if there are results and only on the last page --> <div v-if=" - foot.items.length > 0 && - paginationCurrentPage === - Math.ceil(paginationTotalRows / paginationPerPage) + foot.items.length > 0 && pagination && !pagination.HasNext " class="p-2 text-center text-muted border-top" > @@ -183,16 +181,16 @@ <b-col align-self="center" class="p-0"> <b-pagination id="pagination" - v-model="paginationCurrentPage" - :total-rows="paginationTotalRows" - :per-page="paginationPerPage" + v-model="selectedPage" + :total-rows="pagination ? pagination.TotalCount : 0" + :per-page="pagination ? pagination.PageSize : 0" aria-controls="resultsView" align="center" /> </b-col> <b-col align-self="center" class="p-0"> <b-form-select - v-model="paginationPerPage" + v-model="paginationPageSize" :options="paginationPerPageOptions" style="max-width: 5rem" /> @@ -216,10 +214,8 @@ import useResourceStore from "@/modules/resource/store"; import type { ProjectObject } from "@coscine/api-client/dist/types/Coscine.Api.Project"; import type { ResourceObject } from "@coscine/api-client/dist/types/Coscine.Api.Resources"; -import type { - ItemSearchResult, - SearchResult, -} from "@coscine/api-client/dist/types/Coscine.Api.Search"; +import type { ItemSearchResult } from "@coscine/api-client/dist/types/Coscine.Api.Search"; +import { Pagination } from "../types"; export default defineComponent({ components: { @@ -248,10 +244,10 @@ export default defineComponent({ resultsViewFields: ["type"], resultsViewLoading: true, - - paginationCurrentPage: 1, - paginationPerPage: 100, - paginationPerPageOptions: [5, 10, 20, 50, 100], + + paginationPerPageOptions: [5, 10, 20, 50], + selectedPage: 1, + paginationPageSize: 10 }; }, @@ -294,30 +290,34 @@ export default defineComponent({ }); }, paginationTotalRows(): number { - return this.filteredResults.length; + if(this.searchStore.pagination?.TotalCount){ + return this.searchStore.pagination.TotalCount; + } else return 0; + }, + pagination(): Pagination | null { + return this.searchStore.pagination; }, resultsForTable(): ItemSearchResult[] { const result: ItemSearchResult[] = []; if (this.searchResults) { - if (this.searchResults.items) { - result.push( - ...this.searchResults.items.filter((item) => - this.isFilteredItem(item) - ) - ); - } + result.push( + ...this.searchResults.filter((item) => + this.isFilteredItem(item) + ) + ); } return result; }, - searchResults(): SearchResult | null { + searchResults(): ItemSearchResult[] | null { return this.searchStore.searchResults; }, }, watch: { searchText() { - this.queryData(this.searchText); + this.queryData(this.searchText, this.selectedPage, this.paginationPageSize); }, + selectedProject() { this.selectedResource = null; this.projectResources = null; @@ -326,8 +326,17 @@ export default defineComponent({ this.retrieveResources(); this.retrieveSubProjects(); }, - resultsForTable() { - this.assignResultsFilter(); + + // resultsForTable() { + // this.assignResultsFilter(); + // }, + + selectedPage() { + this.queryData(this.searchText, this.selectedPage, this.paginationPageSize); + }, + + paginationPageSize() { + this.queryData(this.searchText, this.selectedPage, this.paginationPageSize); }, }, @@ -362,11 +371,11 @@ export default defineComponent({ const query = Object.fromEntries(urlSearchParams.entries()); return query !== null ? decodeURIComponent(query.q) : ""; }, - async queryData(query: string) { + async queryData(query: string, pageNumber: number, pageSize: number) { this.resultsViewLoading = true; // attach search query, resulting in "/search?q=<searchTerm>" this.$router.push({ name: "search", query: { q: query } }); - await this.searchStore.retrieveSearchResults(query, this.selectedProject); + await this.searchStore.retrieveSearchResults(query, pageNumber, pageSize, this.selectedProject); this.resultsViewLoading = false; }, async retrieveResources() { @@ -388,13 +397,13 @@ export default defineComponent({ this.projectSubProjects = []; } }, - assignResultsFilter(content: ItemSearchResult[] | null = null) { - if (content) { - this.filteredResults = content; - } else { - this.filteredResults = this.resultsForTable; - } - }, + assignResultsFilter(content: ItemSearchResult[] | null = null) { + if (content) { + this.filteredResults = content; + } else { + this.filteredResults = this.resultsForTable; + } + }, }, }); </script> diff --git a/src/modules/search/store.ts b/src/modules/search/store.ts index 9be713ff27a3699a119d7bfda8229440f1035c02..e09952677d6e71f559b553d46be90aff67502880 100644 --- a/src/modules/search/store.ts +++ b/src/modules/search/store.ts @@ -20,6 +20,7 @@ export const useSearchStore = defineStore({ */ state: (): SearchState => ({ searchResults: null, + pagination: null }), /* @@ -45,6 +46,8 @@ export const useSearchStore = defineStore({ actions: { async retrieveSearchResults( query: string, + pageNumber: number, + pageSize: number, projectObject?: ProjectObject | null ): Promise<boolean> { const notificationStore = useNotificationStore(); @@ -53,7 +56,12 @@ export const useSearchStore = defineStore({ if (projectObject && projectObject.id) { adaptedQuery = `(${adaptedQuery}) + (belongsToProject: "https://purl.org/coscine/projects/${projectObject.id}")`; } - const response = await SearchApi.searchSearch(adaptedQuery); + const response = await SearchApi.searchSearch(adaptedQuery, undefined, undefined, undefined, pageNumber, pageSize); + + if(response.headers["x-pagination"]){ + this.pagination = JSON.parse(response.headers["x-pagination"]); + } + this.searchResults = response.data; return true; } catch (error) { diff --git a/src/modules/search/types.ts b/src/modules/search/types.ts index 982cc5387145b95436da266b24307efa71a41605..ee442c0ab44834b2a9c734bea5272e027185d99f 100644 --- a/src/modules/search/types.ts +++ b/src/modules/search/types.ts @@ -1,4 +1,13 @@ -import type { SearchResult } from "@coscine/api-client/dist/types/Coscine.Api.Search"; +import type { ItemSearchResult } from "@coscine/api-client/dist/types/Coscine.Api.Search"; + +export interface Pagination { + TotalCount: number; + PageSize: number; + CurrentPage: number; + TotalPages: number; + HasNext: boolean; + HasPrevious: boolean; +} export interface SearchState { /* @@ -6,5 +15,6 @@ export interface SearchState { STATE TYPE DEFINITION -------------------------------------------------------------------------------------- */ - searchResults: SearchResult | null; + pagination: Pagination | null; + searchResults: ItemSearchResult[] | null; }