From 50b516d0c5772a15acdb69091ace788ed67fad13 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Fri, 26 Jun 2020 17:54:15 +0800 Subject: [PATCH] feat(webui): pagination for collections closes #216 --- .../src/components/CollectionAddToDialog.vue | 2 +- .../src/components/CollectionEditDialog.vue | 2 +- .../src/services/komga-collections.service.ts | 11 +- komga-webui/src/views/BrowseCollections.vue | 103 +++++++++++++++++- komga-webui/src/views/BrowseLibraries.vue | 13 +-- 5 files changed, 111 insertions(+), 20 deletions(-) diff --git a/komga-webui/src/components/CollectionAddToDialog.vue b/komga-webui/src/components/CollectionAddToDialog.vue index 8a3b0538c..a895d7bc9 100644 --- a/komga-webui/src/components/CollectionAddToDialog.vue +++ b/komga-webui/src/components/CollectionAddToDialog.vue @@ -106,7 +106,7 @@ export default Vue.extend({ this.modal = val if (val) { this.newCollection = '' - this.collections = await this.$komgaCollections.getCollections() + this.collections = (await this.$komgaCollections.getCollections(undefined, undefined, true)).content } }, modal (val) { diff --git a/komga-webui/src/components/CollectionEditDialog.vue b/komga-webui/src/components/CollectionEditDialog.vue index 7d54a0579..91c964490 100644 --- a/komga-webui/src/components/CollectionEditDialog.vue +++ b/komga-webui/src/components/CollectionEditDialog.vue @@ -117,7 +117,7 @@ export default Vue.extend({ async dialogReset (collection: CollectionDto) { this.form.name = collection.name this.form.ordered = collection.ordered - this.collections = await this.$komgaCollections.getCollections() + this.collections = (await this.$komgaCollections.getCollections(undefined, undefined, true)).content }, dialogCancel () { this.$emit('input', false) diff --git a/komga-webui/src/services/komga-collections.service.ts b/komga-webui/src/services/komga-collections.service.ts index 885f48863..2f79839e0 100644 --- a/komga-webui/src/services/komga-collections.service.ts +++ b/komga-webui/src/services/komga-collections.service.ts @@ -11,12 +11,13 @@ export default class KomgaCollectionsService { this.http = http } - async getCollections (libraryIds?: number[]): Promise { + async getCollections (libraryIds?: number[], pageRequest?: PageRequest, unpaged?: boolean, search?: string): Promise> { try { - const params = {} as any - if (libraryIds) { - params.library_id = libraryIds - } + const params = { ...pageRequest } as any + if (libraryIds) params.library_id = libraryIds + if (unpaged) params.unpaged = unpaged + if (search) params.search = search + return (await this.http.get(API_COLLECTIONS, { params: params, paramsSerializer: params => qs.stringify(params, { indices: false }), diff --git a/komga-webui/src/views/BrowseCollections.vue b/komga-webui/src/views/BrowseCollections.vue index 86b510b68..388831d1c 100644 --- a/komga-webui/src/views/BrowseCollections.vue +++ b/komga-webui/src/views/BrowseCollections.vue @@ -9,15 +9,25 @@ {{ library ? library.name : 'All libraries' }} {{ collections.length }} + + + + - + + + @@ -30,6 +40,7 @@ import Badge from '@/components/Badge.vue' import ItemBrowser from '@/components/ItemBrowser.vue' import LibraryActionsMenu from '@/components/LibraryActionsMenu.vue' import LibraryNavigation from '@/components/LibraryNavigation.vue' +import PageSizeSelect from '@/components/PageSizeSelect.vue' import ToolbarSticky from '@/components/ToolbarSticky.vue' import { COLLECTION_CHANGED } from '@/types/events' import Vue from 'vue' @@ -44,11 +55,18 @@ export default Vue.extend({ LibraryNavigation, ItemBrowser, Badge, + PageSizeSelect, }, data: () => { return { library: undefined as LibraryDto | undefined, collections: [] as CollectionDto[], + page: 1, + pageSize: 20, + totalPages: 1, + totalElements: null as number | null, + pageUnwatch: null as any, + pageSizeUnwatch: null as any, } }, props: { @@ -64,11 +82,24 @@ export default Vue.extend({ this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCollections) }, mounted () { + if (this.$cookies.isKey(cookiePageSize)) { + this.pageSize = Number(this.$cookies.get(cookiePageSize)) + } + + // restore from query param + if (this.$route.query.page) this.page = Number(this.$route.query.page) + if (this.$route.query.pageSize) this.pageSize = Number(this.$route.query.pageSize) + this.loadLibrary(this.libraryId) + + this.setWatches() }, beforeRouteUpdate (to, from, next) { if (to.params.libraryId !== from.params.libraryId) { // reset + this.page = 1 + this.totalPages = 1 + this.totalElements = null this.collections = [] this.loadLibrary(Number(to.params.libraryId)) @@ -80,19 +111,81 @@ export default Vue.extend({ isAdmin (): boolean { return this.$store.getters.meAdmin }, + paginationVisible (): number { + switch (this.$vuetify.breakpoint.name) { + case 'xs': + return 5 + case 'sm': + case 'md': + return 10 + case 'lg': + case 'xl': + default: + return 15 + } + }, }, methods: { + setWatches () { + this.pageSizeUnwatch = this.$watch('pageSize', (val) => { + this.$cookies.set(cookiePageSize, val, Infinity) + this.updateRouteAndReload() + }) + + this.pageUnwatch = this.$watch('page', (val) => { + this.updateRoute() + this.loadPage(this.libraryId, val) + }) + }, + unsetWatches () { + this.pageUnwatch() + this.pageSizeUnwatch() + }, + updateRouteAndReload () { + this.unsetWatches() + + this.page = 1 + + this.updateRoute() + this.loadPage(this.libraryId, this.page) + + this.setWatches() + }, + updateRoute () { + this.$router.replace({ + name: this.$route.name, + params: { libraryId: this.$route.params.libraryId }, + query: { + page: `${this.page}`, + pageSize: `${this.pageSize}`, + }, + }).catch(_ => { + }) + }, reloadCollections () { this.loadLibrary(this.libraryId) }, async loadLibrary (libraryId: number) { this.library = this.getLibraryLazy(libraryId) - const lib = libraryId !== 0 ? [libraryId] : undefined - this.collections = await this.$komgaCollections.getCollections(lib) - if (this.collections.length === 0) { + await this.loadPage(libraryId, this.page) + + if (this.totalElements === 0) { await this.$router.push({ name: 'browse-libraries', params: { libraryId: libraryId.toString() } }) } }, + async loadPage (libraryId: number, page: number) { + const pageRequest = { + page: page - 1, + size: this.pageSize, + } as PageRequest + + const lib = libraryId !== 0 ? [libraryId] : undefined + const collectionsPage = await this.$komgaCollections.getCollections(lib, pageRequest) + + this.totalPages = collectionsPage.totalPages + this.totalElements = collectionsPage.totalElements + this.collections = collectionsPage.content + }, getLibraryLazy (libraryId: any): LibraryDto | undefined { if (libraryId !== 0) { return this.$store.getters.getLibraryById(libraryId) diff --git a/komga-webui/src/views/BrowseLibraries.vue b/komga-webui/src/views/BrowseLibraries.vue index 0a6acfe6b..2c87b10a8 100644 --- a/komga-webui/src/views/BrowseLibraries.vue +++ b/komga-webui/src/views/BrowseLibraries.vue @@ -77,7 +77,7 @@ - @@ -178,7 +178,7 @@ export default Vue.extend({ dialogEdit: false, dialogEditSingle: false, dialogAddToCollection: false, - collections: [] as CollectionDto[], + collectionsCount: 0, } }, props: { @@ -245,7 +245,7 @@ export default Vue.extend({ this.totalPages = 1 this.totalElements = null this.series = [] - this.collections = [] + this.collectionsCount = 0 this.loadLibrary(Number(to.params.libraryId)) @@ -322,7 +322,7 @@ export default Vue.extend({ this.library = this.getLibraryLazy(libraryId) const lib = libraryId !== 0 ? [libraryId] : undefined - this.collections = await this.$komgaCollections.getCollections(lib) + this.collectionsCount = (await this.$komgaCollections.getCollections(lib, { size: 1 })).totalElements await this.loadPage(libraryId, this.page, this.sortActive) }, @@ -353,10 +353,7 @@ export default Vue.extend({ pageRequest.sort = [`${sort.key},${sort.order}`] } - let requestLibraryId - if (libraryId !== 0) { - requestLibraryId = libraryId - } + const requestLibraryId = libraryId !== 0 ? libraryId : undefined const seriesPage = await this.$komgaSeries.getSeries(requestLibraryId, pageRequest, undefined, this.filters[1], this.filters[0]) this.totalPages = seriesPage.totalPages