mirror of
https://github.com/gotson/komga.git
synced 2026-05-08 12:35:30 +02:00
Merge pull request #494 from edwinbadillo/recommended-library
feat: Added a 'Recommended' tab in the library views for a library specific dashboard like the home page
This commit is contained in:
commit
638f40831f
16 changed files with 331 additions and 140 deletions
|
|
@ -1,31 +1,78 @@
|
|||
<template>
|
||||
<v-bottom-navigation
|
||||
v-if="collectionsCount > 0 || readListsCount > 0"
|
||||
grow color="primary"
|
||||
:fixed="$vuetify.breakpoint.name === 'xs'"
|
||||
>
|
||||
<v-btn :to="{name: 'browse-libraries', params: {libraryId: libraryId}}">
|
||||
<span>{{ $t('library_navigation.browse') }}</span>
|
||||
<v-icon>mdi-bookshelf</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn
|
||||
v-if="collectionsCount > 0"
|
||||
:to="{name: 'browse-collections', params: {libraryId: libraryId}}"
|
||||
<div>
|
||||
<v-bottom-navigation
|
||||
v-if="show && bottomNavigation"
|
||||
grow color="primary"
|
||||
:fixed="$vuetify.breakpoint.name === 'xs'"
|
||||
>
|
||||
<span>{{ $t('library_navigation.collections') }}</span>
|
||||
<v-icon>mdi-layers-triple</v-icon>
|
||||
</v-btn>
|
||||
<v-btn v-if="showRecommended"
|
||||
:to="{name: 'recommended-libraries', params: {libraryId: libraryId}}"
|
||||
>
|
||||
<span>{{ $t('library_navigation.recommended') }}</span>
|
||||
<v-icon>mdi-star</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn
|
||||
v-if="readListsCount > 0"
|
||||
:to="{name: 'browse-readlists', params: {libraryId: libraryId}}"
|
||||
<v-btn :to="{name: 'browse-libraries', params: {libraryId: libraryId}}">
|
||||
<span>{{ $t('library_navigation.browse') }}</span>
|
||||
<v-icon>mdi-bookshelf</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn
|
||||
v-if="collectionsCount > 0"
|
||||
:to="{name: 'browse-collections', params: {libraryId: libraryId}}"
|
||||
>
|
||||
<span>{{ $t('library_navigation.collections') }}</span>
|
||||
<v-icon>mdi-layers-triple</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn
|
||||
v-if="readListsCount > 0"
|
||||
:to="{name: 'browse-readlists', params: {libraryId: libraryId}}"
|
||||
>
|
||||
<span>{{ $t('library_navigation.readlists') }}</span>
|
||||
<v-icon>mdi-book-multiple</v-icon>
|
||||
</v-btn>
|
||||
|
||||
</v-bottom-navigation>
|
||||
|
||||
<template
|
||||
v-if="show && !bottomNavigation"
|
||||
>
|
||||
<span>{{ $t('library_navigation.readlists') }}</span>
|
||||
<v-icon>mdi-book-multiple</v-icon>
|
||||
</v-btn>
|
||||
<v-btn v-if="showRecommended"
|
||||
:to="{name: 'recommended-libraries', params: {libraryId: libraryId}}"
|
||||
text
|
||||
class="mx-1"
|
||||
>
|
||||
{{ $t('library_navigation.recommended') }}
|
||||
</v-btn>
|
||||
|
||||
</v-bottom-navigation>
|
||||
<v-btn :to="{name: 'browse-libraries', params: {libraryId: libraryId}}"
|
||||
text
|
||||
class="mx-1"
|
||||
>
|
||||
{{ $t('library_navigation.browse') }}
|
||||
</v-btn>
|
||||
|
||||
<v-btn
|
||||
v-if="collectionsCount > 0"
|
||||
:to="{name: 'browse-collections', params: {libraryId: libraryId}}"
|
||||
text
|
||||
class="mx-1"
|
||||
>
|
||||
{{ $t('library_navigation.collections') }}
|
||||
</v-btn>
|
||||
|
||||
<v-btn
|
||||
v-if="readListsCount > 0"
|
||||
:to="{name: 'browse-readlists', params: {libraryId: libraryId}}"
|
||||
text
|
||||
class="mx-1"
|
||||
>
|
||||
{{ $t('library_navigation.readlists') }}
|
||||
</v-btn>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
|
@ -46,31 +93,43 @@ export default Vue.extend({
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
bottomNavigation: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
libraryId: {
|
||||
handler (val) {
|
||||
handler(val) {
|
||||
this.loadCounts(val)
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
created () {
|
||||
created() {
|
||||
this.$eventHub.$on(COLLECTION_CHANGED, this.reloadCounts)
|
||||
this.$eventHub.$on(READLIST_CHANGED, this.reloadCounts)
|
||||
},
|
||||
beforeDestroy () {
|
||||
beforeDestroy() {
|
||||
this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCounts)
|
||||
this.$eventHub.$off(READLIST_CHANGED, this.reloadCounts)
|
||||
},
|
||||
computed: {
|
||||
showRecommended(): boolean {
|
||||
return this.libraryId !== LIBRARIES_ALL
|
||||
},
|
||||
show(): boolean {
|
||||
return this.collectionsCount > 0 || this.readListsCount > 0 || this.showRecommended
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
reloadCounts () {
|
||||
reloadCounts() {
|
||||
this.loadCounts(this.libraryId)
|
||||
},
|
||||
async loadCounts (libraryId: string) {
|
||||
async loadCounts(libraryId: string) {
|
||||
const lib = libraryId !== LIBRARIES_ALL ? [libraryId] : undefined
|
||||
this.collectionsCount = (await this.$komgaCollections.getCollections(lib, { size: 1 })).totalElements
|
||||
this.readListsCount = (await this.$komgaReadLists.getReadLists(lib, { size: 1 })).totalElements
|
||||
this.collectionsCount = (await this.$komgaCollections.getCollections(lib, {size: 1})).totalElements
|
||||
this.readListsCount = (await this.$komgaReadLists.getReadLists(lib, {size: 1})).totalElements
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -462,7 +462,8 @@
|
|||
"library_navigation": {
|
||||
"browse": "Browse",
|
||||
"collections": "Collections",
|
||||
"readlists": "Read Lists"
|
||||
"readlists": "Read Lists",
|
||||
"recommended": "Recommended"
|
||||
},
|
||||
"login": {
|
||||
"create_user_account": "Create user account",
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ export const persistedModule: Module<any, any> = {
|
|||
library: {
|
||||
filter: {},
|
||||
sort: {},
|
||||
route: {},
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
|
|
@ -38,6 +39,9 @@ export const persistedModule: Module<any, any> = {
|
|||
getLibrarySort: (state) => (id: string) => {
|
||||
return state.library.sort[id]
|
||||
},
|
||||
getLibraryRoute: (state) => (id: string) => {
|
||||
return state.library.route[id]
|
||||
},
|
||||
},
|
||||
mutations: {
|
||||
setLocale(state, val) {
|
||||
|
|
@ -82,5 +86,8 @@ export const persistedModule: Module<any, any> = {
|
|||
setLibrarySort(state, {id, sort}) {
|
||||
state.library.sort[id] = sort
|
||||
},
|
||||
setLibraryRoute(state, {id, route}) {
|
||||
state.library.route[id] = route
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,22 +2,37 @@ import urls from '@/functions/urls'
|
|||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import store from './store'
|
||||
import {LIBRARIES_ALL, LIBRARY_ROUTE} from "@/types/library";
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
const lStore = store as any
|
||||
|
||||
const adminGuard = (to: any, from: any, next: any) => {
|
||||
if (!lStore.getters.meAdmin) next({ name: 'home' })
|
||||
if (!lStore.getters.meAdmin) next({name: 'home'})
|
||||
else next()
|
||||
}
|
||||
|
||||
const noLibraryGuard = (to: any, from: any, next: any) => {
|
||||
if (lStore.state.komgaLibraries.libraries.length === 0) {
|
||||
next({ name: 'welcome' })
|
||||
next({name: 'welcome'})
|
||||
} else next()
|
||||
}
|
||||
|
||||
const getLibraryRoute = (libraryId: string) => {
|
||||
switch ((lStore.getters.getLibraryRoute(libraryId) as LIBRARY_ROUTE)) {
|
||||
case LIBRARY_ROUTE.COLLECTIONS:
|
||||
return 'browse-collections'
|
||||
case LIBRARY_ROUTE.READLISTS:
|
||||
return 'browse-readlists'
|
||||
case LIBRARY_ROUTE.BROWSE:
|
||||
return 'browse-libraries'
|
||||
case LIBRARY_ROUTE.RECOMMENDED:
|
||||
default:
|
||||
return 'recommended-libraries'
|
||||
}
|
||||
}
|
||||
|
||||
const router = new Router({
|
||||
mode: 'history',
|
||||
base: urls.base,
|
||||
|
|
@ -25,7 +40,7 @@ const router = new Router({
|
|||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
redirect: { name: 'dashboard' },
|
||||
redirect: {name: 'dashboard'},
|
||||
component: () => import(/* webpackChunkName: "home" */ './views/Home.vue'),
|
||||
children: [
|
||||
{
|
||||
|
|
@ -42,7 +57,7 @@ const router = new Router({
|
|||
{
|
||||
path: '/settings',
|
||||
name: 'settings',
|
||||
redirect: { name: 'settings-analysis' },
|
||||
redirect: {name: 'settings-analysis'},
|
||||
component: () => import(/* webpackChunkName: "settings" */ './views/Settings.vue'),
|
||||
children: [
|
||||
{
|
||||
|
|
@ -83,50 +98,65 @@ const router = new Router({
|
|||
name: 'account',
|
||||
component: () => import(/* webpackChunkName: "account" */ './views/AccountSettings.vue'),
|
||||
},
|
||||
{
|
||||
path: '/libraries/:libraryId?',
|
||||
name: 'libraries',
|
||||
redirect: (route) => ({
|
||||
name: getLibraryRoute(route.params.libraryId || LIBRARIES_ALL),
|
||||
params: {libraryId: route.params.libraryId || LIBRARIES_ALL},
|
||||
}),
|
||||
},
|
||||
{
|
||||
path: '/libraries/:libraryId/recommended',
|
||||
name: 'recommended-libraries',
|
||||
beforeEnter: noLibraryGuard,
|
||||
component: () => import(/* webpackChunkName: "dashboard" */ './views/Dashboard.vue'),
|
||||
props: (route) => ({libraryId: route.params.libraryId}),
|
||||
},
|
||||
{
|
||||
path: '/libraries/:libraryId/series',
|
||||
name: 'browse-libraries',
|
||||
beforeEnter: noLibraryGuard,
|
||||
component: () => import(/* webpackChunkName: "browse-libraries" */ './views/BrowseLibraries.vue'),
|
||||
props: (route) => ({ libraryId: route.params.libraryId }),
|
||||
props: (route) => ({libraryId: route.params.libraryId}),
|
||||
},
|
||||
{
|
||||
path: '/libraries/:libraryId/collections',
|
||||
name: 'browse-collections',
|
||||
beforeEnter: noLibraryGuard,
|
||||
component: () => import(/* webpackChunkName: "browse-collections" */ './views/BrowseCollections.vue'),
|
||||
props: (route) => ({ libraryId: route.params.libraryId }),
|
||||
props: (route) => ({libraryId: route.params.libraryId}),
|
||||
},
|
||||
{
|
||||
path: '/libraries/:libraryId/readlists',
|
||||
name: 'browse-readlists',
|
||||
beforeEnter: noLibraryGuard,
|
||||
component: () => import(/* webpackChunkName: "browse-readlists" */ './views/BrowseReadLists.vue'),
|
||||
props: (route) => ({ libraryId: route.params.libraryId }),
|
||||
props: (route) => ({libraryId: route.params.libraryId}),
|
||||
},
|
||||
{
|
||||
path: '/collections/:collectionId',
|
||||
name: 'browse-collection',
|
||||
component: () => import(/* webpackChunkName: "browse-collection" */ './views/BrowseCollection.vue'),
|
||||
props: (route) => ({ collectionId: route.params.collectionId }),
|
||||
props: (route) => ({collectionId: route.params.collectionId}),
|
||||
},
|
||||
{
|
||||
path: '/readlists/:readListId',
|
||||
name: 'browse-readlist',
|
||||
component: () => import(/* webpackChunkName: "browse-readlist" */ './views/BrowseReadList.vue'),
|
||||
props: (route) => ({ readListId: route.params.readListId }),
|
||||
props: (route) => ({readListId: route.params.readListId}),
|
||||
},
|
||||
{
|
||||
path: '/series/:seriesId',
|
||||
name: 'browse-series',
|
||||
component: () => import(/* webpackChunkName: "browse-series" */ './views/BrowseSeries.vue'),
|
||||
props: (route) => ({ seriesId: route.params.seriesId }),
|
||||
props: (route) => ({seriesId: route.params.seriesId}),
|
||||
},
|
||||
{
|
||||
path: '/book/:bookId',
|
||||
name: 'browse-book',
|
||||
component: () => import(/* webpackChunkName: "browse-book" */ './views/BrowseBook.vue'),
|
||||
props: (route) => ({ bookId: route.params.bookId }),
|
||||
props: (route) => ({bookId: route.params.bookId}),
|
||||
},
|
||||
{
|
||||
path: '/search',
|
||||
|
|
@ -155,7 +185,7 @@ const router = new Router({
|
|||
path: '/book/:bookId/read',
|
||||
name: 'read-book',
|
||||
component: () => import(/* webpackChunkName: "read-book" */ './views/BookReader.vue'),
|
||||
props: (route) => ({ bookId: route.params.bookId }),
|
||||
props: (route) => ({bookId: route.params.bookId}),
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
|
|
@ -163,12 +193,12 @@ const router = new Router({
|
|||
component: () => import(/* webpackChunkName: "notfound" */ './views/PageNotFound.vue'),
|
||||
},
|
||||
],
|
||||
scrollBehavior (to, from, savedPosition) {
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
if (savedPosition) {
|
||||
return savedPosition
|
||||
} else {
|
||||
if (to.name !== from.name) {
|
||||
return { x: 0, y: 0 }
|
||||
return {x: 0, y: 0}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -179,7 +209,7 @@ router.beforeEach((to, from, next) => {
|
|||
document.title = 'Komga'
|
||||
}
|
||||
if (to.name !== 'startup' && to.name !== 'login' && !lStore.getters.authenticated) {
|
||||
next({ name: 'startup', query: { redirect: to.fullPath } })
|
||||
next({name: 'startup', query: {redirect: to.fullPath}})
|
||||
} else next()
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -40,10 +40,14 @@ export default class KomgaBooksService {
|
|||
}
|
||||
}
|
||||
|
||||
async getBooksOnDeck (pageRequest?: PageRequest): Promise<Page<BookDto>> {
|
||||
async getBooksOnDeck (libraryId?: string, pageRequest?: PageRequest): Promise<Page<BookDto>> {
|
||||
try {
|
||||
const params = { ...pageRequest } as any
|
||||
if (libraryId) {
|
||||
params.library_id = libraryId
|
||||
}
|
||||
return (await this.http.get(`${API_BOOKS}/ondeck`, {
|
||||
params: { ...pageRequest },
|
||||
params: params,
|
||||
})).data
|
||||
} catch (e) {
|
||||
let msg = 'An error occurred while trying to retrieve books on deck'
|
||||
|
|
|
|||
|
|
@ -43,9 +43,12 @@ export default class KomgaSeriesService {
|
|||
}
|
||||
}
|
||||
|
||||
async getNewSeries (pageRequest?: PageRequest): Promise<Page<SeriesDto>> {
|
||||
async getNewSeries (libraryId?: string, pageRequest?: PageRequest): Promise<Page<SeriesDto>> {
|
||||
try {
|
||||
const params = { ...pageRequest } as any
|
||||
if (libraryId) {
|
||||
params.library_id = libraryId
|
||||
}
|
||||
return (await this.http.get(`${API_SERIES}/new`, {
|
||||
params: params,
|
||||
})).data
|
||||
|
|
@ -58,9 +61,12 @@ export default class KomgaSeriesService {
|
|||
}
|
||||
}
|
||||
|
||||
async getUpdatedSeries (pageRequest?: PageRequest): Promise<Page<SeriesDto>> {
|
||||
async getUpdatedSeries (libraryId?: string, pageRequest?: PageRequest): Promise<Page<SeriesDto>> {
|
||||
try {
|
||||
const params = { ...pageRequest } as any
|
||||
if (libraryId) {
|
||||
params.library_id = libraryId
|
||||
}
|
||||
return (await this.http.get(`${API_SERIES}/updated`, {
|
||||
params: params,
|
||||
})).data
|
||||
|
|
|
|||
|
|
@ -1 +1,8 @@
|
|||
export const LIBRARIES_ALL = 'all'
|
||||
|
||||
export enum LIBRARY_ROUTE {
|
||||
BROWSE = 'BROWSE',
|
||||
RECOMMENDED = 'RECOMMENDED',
|
||||
COLLECTIONS = 'COLLECTIONS',
|
||||
READLISTS = 'READLISTS'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,14 @@
|
|||
|
||||
<v-spacer/>
|
||||
|
||||
<library-navigation v-if="$vuetify.breakpoint.name !== 'xs'" :libraryId="libraryId"/>
|
||||
|
||||
<v-spacer/>
|
||||
|
||||
<page-size-select v-model="pageSize"/>
|
||||
</toolbar-sticky>
|
||||
|
||||
<library-navigation :libraryId="libraryId"/>
|
||||
<library-navigation v-if="$vuetify.breakpoint.name === 'xs'" :libraryId="libraryId" bottom-navigation/>
|
||||
|
||||
<v-container fluid>
|
||||
<v-pagination
|
||||
|
|
@ -53,7 +57,7 @@ import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
|||
import {COLLECTION_CHANGED, COLLECTION_DELETED, LIBRARY_CHANGED} from '@/types/events'
|
||||
import Vue from 'vue'
|
||||
import {Location} from 'vue-router'
|
||||
import {LIBRARIES_ALL} from '@/types/library'
|
||||
import {LIBRARIES_ALL, LIBRARY_ROUTE} from '@/types/library'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'BrowseCollections',
|
||||
|
|
@ -82,17 +86,18 @@ export default Vue.extend({
|
|||
default: LIBRARIES_ALL,
|
||||
},
|
||||
},
|
||||
created () {
|
||||
created() {
|
||||
this.$eventHub.$on(COLLECTION_CHANGED, this.reloadCollections)
|
||||
this.$eventHub.$on(COLLECTION_DELETED, this.reloadCollections)
|
||||
this.$eventHub.$on(LIBRARY_CHANGED, this.reloadLibrary)
|
||||
},
|
||||
beforeDestroy () {
|
||||
beforeDestroy() {
|
||||
this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCollections)
|
||||
this.$eventHub.$off(COLLECTION_DELETED, this.reloadCollections)
|
||||
this.$eventHub.$off(LIBRARY_CHANGED, this.reloadLibrary)
|
||||
},
|
||||
mounted () {
|
||||
mounted() {
|
||||
this.$store.commit('setLibraryRoute', {id: this.libraryId, route: LIBRARY_ROUTE.COLLECTIONS})
|
||||
this.pageSize = this.$store.state.persistedState.browsingPageSize || this.pageSize
|
||||
|
||||
// restore from query param
|
||||
|
|
@ -103,7 +108,7 @@ export default Vue.extend({
|
|||
|
||||
this.setWatches()
|
||||
},
|
||||
beforeRouteUpdate (to, from, next) {
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
if (to.params.libraryId !== from.params.libraryId) {
|
||||
// reset
|
||||
this.page = 1
|
||||
|
|
@ -117,10 +122,10 @@ export default Vue.extend({
|
|||
next()
|
||||
},
|
||||
computed: {
|
||||
isAdmin (): boolean {
|
||||
isAdmin(): boolean {
|
||||
return this.$store.getters.meAdmin
|
||||
},
|
||||
paginationVisible (): number {
|
||||
paginationVisible(): number {
|
||||
switch (this.$vuetify.breakpoint.name) {
|
||||
case 'xs':
|
||||
return 5
|
||||
|
|
@ -135,7 +140,7 @@ export default Vue.extend({
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
setWatches () {
|
||||
setWatches() {
|
||||
this.pageSizeUnwatch = this.$watch('pageSize', (val) => {
|
||||
this.$store.commit('setBrowsingPageSize', val)
|
||||
this.updateRouteAndReload()
|
||||
|
|
@ -146,11 +151,11 @@ export default Vue.extend({
|
|||
this.loadPage(this.libraryId, val)
|
||||
})
|
||||
},
|
||||
unsetWatches () {
|
||||
unsetWatches() {
|
||||
this.pageUnwatch()
|
||||
this.pageSizeUnwatch()
|
||||
},
|
||||
updateRouteAndReload () {
|
||||
updateRouteAndReload() {
|
||||
this.unsetWatches()
|
||||
|
||||
this.page = 1
|
||||
|
|
@ -160,10 +165,10 @@ export default Vue.extend({
|
|||
|
||||
this.setWatches()
|
||||
},
|
||||
updateRoute () {
|
||||
updateRoute() {
|
||||
this.$router.replace({
|
||||
name: this.$route.name,
|
||||
params: { libraryId: this.$route.params.libraryId },
|
||||
params: {libraryId: this.$route.params.libraryId},
|
||||
query: {
|
||||
page: `${this.page}`,
|
||||
pageSize: `${this.pageSize}`,
|
||||
|
|
@ -171,23 +176,23 @@ export default Vue.extend({
|
|||
} as Location).catch((_: any) => {
|
||||
})
|
||||
},
|
||||
reloadCollections () {
|
||||
reloadCollections() {
|
||||
this.loadLibrary(this.libraryId)
|
||||
},
|
||||
reloadLibrary (event: EventLibraryChanged) {
|
||||
reloadLibrary(event: EventLibraryChanged) {
|
||||
if (event.id === this.libraryId) {
|
||||
this.loadLibrary(this.libraryId)
|
||||
}
|
||||
},
|
||||
async loadLibrary (libraryId: string) {
|
||||
async loadLibrary(libraryId: string) {
|
||||
this.library = this.getLibraryLazy(libraryId)
|
||||
await this.loadPage(libraryId, this.page)
|
||||
|
||||
if (this.totalElements === 0) {
|
||||
await this.$router.push({ name: 'browse-libraries', params: { libraryId: libraryId.toString() } })
|
||||
await this.$router.push({name: 'browse-libraries', params: {libraryId: libraryId.toString()}})
|
||||
}
|
||||
},
|
||||
async loadPage (libraryId: string, page: number) {
|
||||
async loadPage(libraryId: string, page: number) {
|
||||
const pageRequest = {
|
||||
page: page - 1,
|
||||
size: this.pageSize,
|
||||
|
|
@ -200,14 +205,14 @@ export default Vue.extend({
|
|||
this.totalElements = collectionsPage.totalElements
|
||||
this.collections = collectionsPage.content
|
||||
},
|
||||
getLibraryLazy (libraryId: string): LibraryDto | undefined {
|
||||
getLibraryLazy(libraryId: string): LibraryDto | undefined {
|
||||
if (libraryId !== LIBRARIES_ALL) {
|
||||
return this.$store.getters.getLibraryById(libraryId)
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
},
|
||||
editSingleCollection (collection: CollectionDto) {
|
||||
editSingleCollection(collection: CollectionDto) {
|
||||
this.$store.dispatch('dialogEditCollection', collection)
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@
|
|||
|
||||
<v-spacer/>
|
||||
|
||||
<library-navigation v-if="$vuetify.breakpoint.name !== 'xs'" :libraryId="libraryId"/>
|
||||
|
||||
<v-spacer/>
|
||||
|
||||
<page-size-select v-model="pageSize"/>
|
||||
|
||||
<v-btn icon @click="drawer = !drawer">
|
||||
|
|
@ -30,7 +34,7 @@
|
|||
@edit="editMultipleSeries"
|
||||
/>
|
||||
|
||||
<library-navigation :libraryId="libraryId"/>
|
||||
<library-navigation v-if="$vuetify.breakpoint.name === 'xs'" :libraryId="libraryId" bottom-navigation/>
|
||||
|
||||
<filter-drawer v-model="drawer">
|
||||
<template v-slot:default>
|
||||
|
|
@ -106,7 +110,7 @@ import {SeriesStatus, SeriesStatusKeyValue} from '@/types/enum-series'
|
|||
import {LIBRARY_CHANGED, LIBRARY_DELETED, SERIES_CHANGED} from '@/types/events'
|
||||
import Vue from 'vue'
|
||||
import {Location} from 'vue-router'
|
||||
import {LIBRARIES_ALL} from '@/types/library'
|
||||
import {LIBRARIES_ALL, LIBRARY_ROUTE} from '@/types/library'
|
||||
import FilterDrawer from '@/components/FilterDrawer.vue'
|
||||
import SortList from '@/components/SortList.vue'
|
||||
import FilterPanels from '@/components/FilterPanels.vue'
|
||||
|
|
@ -186,6 +190,7 @@ export default Vue.extend({
|
|||
this.$eventHub.$off(LIBRARY_CHANGED, this.reloadLibrary)
|
||||
},
|
||||
async mounted() {
|
||||
this.$store.commit('setLibraryRoute', {id: this.libraryId, route: LIBRARY_ROUTE.BROWSE})
|
||||
this.pageSize = this.$store.state.persistedState.browsingPageSize || this.pageSize
|
||||
|
||||
// restore from query param
|
||||
|
|
@ -428,8 +433,8 @@ export default Vue.extend({
|
|||
this.totalElements = seriesPage.totalElements
|
||||
this.series = seriesPage.content
|
||||
},
|
||||
getLibraryLazy(libraryId: any): LibraryDto | undefined {
|
||||
if (libraryId !== 0) {
|
||||
getLibraryLazy (libraryId: string): LibraryDto | undefined {
|
||||
if (libraryId !== LIBRARIES_ALL) {
|
||||
return this.$store.getters.getLibraryById(libraryId)
|
||||
} else {
|
||||
return undefined
|
||||
|
|
|
|||
|
|
@ -14,10 +14,14 @@
|
|||
|
||||
<v-spacer/>
|
||||
|
||||
<library-navigation v-if="$vuetify.breakpoint.name !== 'xs'" :libraryId="libraryId"/>
|
||||
|
||||
<v-spacer/>
|
||||
|
||||
<page-size-select v-model="pageSize"/>
|
||||
</toolbar-sticky>
|
||||
|
||||
<library-navigation :libraryId="libraryId"/>
|
||||
<library-navigation v-if="$vuetify.breakpoint.name === 'xs'" :libraryId="libraryId" bottom-navigation/>
|
||||
|
||||
<v-container fluid>
|
||||
<v-pagination
|
||||
|
|
@ -53,7 +57,7 @@ import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
|||
import {LIBRARY_CHANGED, READLIST_CHANGED, READLIST_DELETED} from '@/types/events'
|
||||
import Vue from 'vue'
|
||||
import {Location} from 'vue-router'
|
||||
import {LIBRARIES_ALL} from '@/types/library'
|
||||
import {LIBRARIES_ALL, LIBRARY_ROUTE} from '@/types/library'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'BrowseReadLists',
|
||||
|
|
@ -93,6 +97,7 @@ export default Vue.extend({
|
|||
this.$eventHub.$off(LIBRARY_CHANGED, this.reloadLibrary)
|
||||
},
|
||||
mounted () {
|
||||
this.$store.commit('setLibraryRoute', {id: this.libraryId, route: LIBRARY_ROUTE.READLISTS})
|
||||
this.pageSize = this.$store.state.persistedState.browsingPageSize || this.pageSize
|
||||
|
||||
// restore from query param
|
||||
|
|
|
|||
|
|
@ -1,5 +1,24 @@
|
|||
<template>
|
||||
<div>
|
||||
<div :style="$vuetify.breakpoint.name === 'xs' ? 'margin-bottom: 56px' : undefined">
|
||||
<toolbar-sticky v-if="showLibraryBar && selectedSeries.length === 0">
|
||||
<!-- Action menu -->
|
||||
<library-actions-menu v-if="library"
|
||||
:library="library"/>
|
||||
|
||||
<v-toolbar-title>
|
||||
<span>{{ library ? library.name : $t('common.all_libraries') }}</span>
|
||||
</v-toolbar-title>
|
||||
|
||||
<v-spacer/>
|
||||
|
||||
<library-navigation v-if="showLibraryBar && $vuetify.breakpoint.name !== 'xs'" :libraryId="libraryId"/>
|
||||
|
||||
<v-spacer/>
|
||||
|
||||
</toolbar-sticky>
|
||||
|
||||
<library-navigation v-if="showLibraryBar && $vuetify.breakpoint.name === 'xs'" :libraryId="libraryId" bottom-navigation/>
|
||||
|
||||
<series-multi-select-bar
|
||||
v-model="selectedSeries"
|
||||
@unselect-all="selectedSeries = []"
|
||||
|
|
@ -110,23 +129,31 @@ import SeriesMultiSelectBar from '@/components/bars/SeriesMultiSelectBar.vue'
|
|||
import EmptyState from '@/components/EmptyState.vue'
|
||||
import HorizontalScroller from '@/components/HorizontalScroller.vue'
|
||||
import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
|
||||
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
||||
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
||||
import {ReadStatus} from '@/types/enum-books'
|
||||
import {BookDto} from '@/types/komga-books'
|
||||
import {BOOK_CHANGED, LIBRARY_DELETED, SERIES_CHANGED} from '@/types/events'
|
||||
import Vue from 'vue'
|
||||
import {SeriesDto} from "@/types/komga-series";
|
||||
import {LIBRARIES_ALL, LIBRARY_ROUTE} from "@/types/library";
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'Dashboard',
|
||||
components: {
|
||||
HorizontalScroller,
|
||||
EmptyState,
|
||||
ToolbarSticky,
|
||||
LibraryNavigation,
|
||||
ItemBrowser,
|
||||
BooksMultiSelectBar,
|
||||
SeriesMultiSelectBar,
|
||||
LibraryActionsMenu,
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
library: undefined as LibraryDto | undefined,
|
||||
newSeries: [] as SeriesDto[],
|
||||
updatedSeries: [] as SeriesDto[],
|
||||
latestBooks: [] as BookDto[],
|
||||
|
|
@ -136,57 +163,81 @@ export default Vue.extend({
|
|||
selectedBooks: [] as BookDto[],
|
||||
}
|
||||
},
|
||||
created () {
|
||||
created() {
|
||||
this.$eventHub.$on(LIBRARY_DELETED, this.libraryDeleted)
|
||||
this.$eventHub.$on(SERIES_CHANGED, this.loadAll)
|
||||
this.$eventHub.$on(BOOK_CHANGED, this.loadAll)
|
||||
this.$eventHub.$on(SERIES_CHANGED, this.reload)
|
||||
this.$eventHub.$on(BOOK_CHANGED, this.reload)
|
||||
},
|
||||
beforeDestroy () {
|
||||
beforeDestroy() {
|
||||
this.$eventHub.$off(LIBRARY_DELETED, this.libraryDeleted)
|
||||
this.$eventHub.$off(SERIES_CHANGED, this.loadAll)
|
||||
this.$eventHub.$off(BOOK_CHANGED, this.loadAll)
|
||||
this.$eventHub.$off(SERIES_CHANGED, this.reload)
|
||||
this.$eventHub.$off(BOOK_CHANGED, this.reload)
|
||||
},
|
||||
mounted () {
|
||||
this.loadAll()
|
||||
mounted() {
|
||||
if(this.showLibraryBar) this.$store.commit('setLibraryRoute', {id: this.libraryId, route: LIBRARY_ROUTE.RECOMMENDED})
|
||||
this.reload()
|
||||
},
|
||||
props: {
|
||||
libraryId: {
|
||||
type: String,
|
||||
default: LIBRARIES_ALL,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedSeries (val: SeriesDto[]) {
|
||||
selectedSeries(val: SeriesDto[]) {
|
||||
val.forEach(i => this.replaceSeries(i))
|
||||
},
|
||||
selectedBooks (val: BookDto[]) {
|
||||
selectedBooks(val: BookDto[]) {
|
||||
val.forEach(i => this.replaceBook(i))
|
||||
},
|
||||
},
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
if (to.params.libraryId !== from.params.libraryId) {
|
||||
this.loadAll(to.params.libraryId)
|
||||
}
|
||||
|
||||
next()
|
||||
},
|
||||
computed: {
|
||||
fixedCardWidth (): number {
|
||||
fixedCardWidth(): number {
|
||||
return this.$vuetify.breakpoint.name === 'xs' ? 120 : 150
|
||||
},
|
||||
allEmpty (): boolean {
|
||||
allEmpty(): boolean {
|
||||
return this.newSeries.length === 0 &&
|
||||
this.updatedSeries.length === 0 &&
|
||||
this.latestBooks.length === 0 &&
|
||||
this.inProgressBooks.length === 0 &&
|
||||
this.onDeckBooks.length === 0
|
||||
},
|
||||
showLibraryBar(): boolean {
|
||||
return this.libraryId !== LIBRARIES_ALL
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
libraryDeleted () {
|
||||
getRequestLibraryId(libraryId: string): string | undefined {
|
||||
return libraryId !== LIBRARIES_ALL ? libraryId : undefined
|
||||
},
|
||||
libraryDeleted() {
|
||||
if (this.$store.state.komgaLibraries.libraries.length === 0) {
|
||||
this.$router.push({ name: 'welcome' })
|
||||
this.$router.push({name: 'welcome'})
|
||||
} else {
|
||||
this.loadAll()
|
||||
this.reload()
|
||||
}
|
||||
},
|
||||
loadAll () {
|
||||
reload() {
|
||||
this.loadAll(this.libraryId)
|
||||
},
|
||||
loadAll(libraryId: string) {
|
||||
this.library = this.getLibraryLazy(libraryId)
|
||||
this.selectedSeries = []
|
||||
this.selectedBooks = []
|
||||
this.loadNewSeries()
|
||||
this.loadUpdatedSeries()
|
||||
this.loadLatestBooks()
|
||||
this.loadInProgressBooks()
|
||||
this.loadOnDeckBooks()
|
||||
this.loadNewSeries(libraryId)
|
||||
this.loadUpdatedSeries(libraryId)
|
||||
this.loadLatestBooks(libraryId)
|
||||
this.loadInProgressBooks(libraryId)
|
||||
this.loadOnDeckBooks(libraryId)
|
||||
},
|
||||
replaceSeries (series: SeriesDto) {
|
||||
replaceSeries(series: SeriesDto) {
|
||||
let index = this.newSeries.findIndex(x => x.id === series.id)
|
||||
if (index !== -1) {
|
||||
this.newSeries.splice(index, 1, series)
|
||||
|
|
@ -196,7 +247,7 @@ export default Vue.extend({
|
|||
this.updatedSeries.splice(index, 1, series)
|
||||
}
|
||||
},
|
||||
replaceBook (book: BookDto) {
|
||||
replaceBook(book: BookDto) {
|
||||
let index = this.latestBooks.findIndex(x => x.id === book.id)
|
||||
if (index !== -1) {
|
||||
this.latestBooks.splice(index, 1, book)
|
||||
|
|
@ -210,36 +261,36 @@ export default Vue.extend({
|
|||
this.onDeckBooks.splice(index, 1, book)
|
||||
}
|
||||
},
|
||||
async loadNewSeries () {
|
||||
this.newSeries = (await this.$komgaSeries.getNewSeries()).content
|
||||
async loadNewSeries(libraryId: string) {
|
||||
this.newSeries = (await this.$komgaSeries.getNewSeries(this.getRequestLibraryId(libraryId))).content
|
||||
},
|
||||
async loadUpdatedSeries () {
|
||||
this.updatedSeries = (await this.$komgaSeries.getUpdatedSeries()).content
|
||||
async loadUpdatedSeries(libraryId: string) {
|
||||
this.updatedSeries = (await this.$komgaSeries.getUpdatedSeries(this.getRequestLibraryId(libraryId))).content
|
||||
},
|
||||
async loadLatestBooks () {
|
||||
async loadLatestBooks(libraryId: string) {
|
||||
const pageRequest = {
|
||||
sort: ['createdDate,desc'],
|
||||
} as PageRequest
|
||||
|
||||
this.latestBooks = (await this.$komgaBooks.getBooks(undefined, pageRequest)).content
|
||||
this.latestBooks = (await this.$komgaBooks.getBooks(this.getRequestLibraryId(libraryId), pageRequest)).content
|
||||
},
|
||||
async loadInProgressBooks () {
|
||||
async loadInProgressBooks(libraryId: string) {
|
||||
const pageRequest = {
|
||||
sort: ['readProgress.lastModified,desc'],
|
||||
} as PageRequest
|
||||
|
||||
this.inProgressBooks = (await this.$komgaBooks.getBooks(undefined, pageRequest, undefined, undefined, [ReadStatus.IN_PROGRESS])).content
|
||||
this.inProgressBooks = (await this.$komgaBooks.getBooks(this.getRequestLibraryId(libraryId), pageRequest, undefined, undefined, [ReadStatus.IN_PROGRESS])).content
|
||||
},
|
||||
async loadOnDeckBooks () {
|
||||
this.onDeckBooks = (await this.$komgaBooks.getBooksOnDeck()).content
|
||||
async loadOnDeckBooks(libraryId: string) {
|
||||
this.onDeckBooks = (await this.$komgaBooks.getBooksOnDeck(this.getRequestLibraryId(libraryId))).content
|
||||
},
|
||||
singleEditSeries (series: SeriesDto) {
|
||||
singleEditSeries(series: SeriesDto) {
|
||||
this.$store.dispatch('dialogUpdateSeries', series)
|
||||
},
|
||||
singleEditBook (book: BookDto) {
|
||||
singleEditBook(book: BookDto) {
|
||||
this.$store.dispatch('dialogUpdateBooks', book)
|
||||
},
|
||||
async markSelectedSeriesRead () {
|
||||
async markSelectedSeriesRead() {
|
||||
await Promise.all(this.selectedSeries.map(s =>
|
||||
this.$komgaSeries.markAsRead(s.id),
|
||||
))
|
||||
|
|
@ -247,7 +298,7 @@ export default Vue.extend({
|
|||
this.$komgaSeries.getOneSeries(s.id),
|
||||
))
|
||||
},
|
||||
async markSelectedSeriesUnread () {
|
||||
async markSelectedSeriesUnread() {
|
||||
await Promise.all(this.selectedSeries.map(s =>
|
||||
this.$komgaSeries.markAsUnread(s.id),
|
||||
))
|
||||
|
|
@ -255,27 +306,27 @@ export default Vue.extend({
|
|||
this.$komgaSeries.getOneSeries(s.id),
|
||||
))
|
||||
},
|
||||
addToCollection () {
|
||||
addToCollection() {
|
||||
this.$store.dispatch('dialogAddSeriesToCollection', this.selectedSeries)
|
||||
},
|
||||
editMultipleSeries () {
|
||||
editMultipleSeries() {
|
||||
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
|
||||
},
|
||||
editMultipleBooks () {
|
||||
editMultipleBooks() {
|
||||
this.$store.dispatch('dialogUpdateBooks', this.selectedBooks)
|
||||
},
|
||||
addToReadList () {
|
||||
addToReadList() {
|
||||
this.$store.dispatch('dialogAddBooksToReadList', this.selectedBooks)
|
||||
},
|
||||
async markSelectedBooksRead () {
|
||||
async markSelectedBooksRead() {
|
||||
await Promise.all(this.selectedBooks.map(b =>
|
||||
this.$komgaBooks.updateReadProgress(b.id, { completed: true }),
|
||||
this.$komgaBooks.updateReadProgress(b.id, {completed: true}),
|
||||
))
|
||||
this.selectedBooks = await Promise.all(this.selectedBooks.map(b =>
|
||||
this.$komgaBooks.getBook(b.id),
|
||||
))
|
||||
},
|
||||
async markSelectedBooksUnread () {
|
||||
async markSelectedBooksUnread() {
|
||||
await Promise.all(this.selectedBooks.map(b =>
|
||||
this.$komgaBooks.deleteReadProgress(b.id),
|
||||
))
|
||||
|
|
@ -283,6 +334,13 @@ export default Vue.extend({
|
|||
this.$komgaBooks.getBook(b.id),
|
||||
))
|
||||
},
|
||||
getLibraryLazy(libraryId: string): LibraryDto | undefined {
|
||||
if (libraryId !== LIBRARIES_ALL) {
|
||||
return this.$store.getters.getLibraryById(libraryId)
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
<v-divider/>
|
||||
|
||||
<v-list>
|
||||
<v-list-item :to="{name: 'home'}" exact>
|
||||
<v-list-item :to="{name: 'dashboard'}">
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-home</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item :to="{name:'browse-libraries', params: {libraryId: 'all'}}">
|
||||
<v-list-item :to="{name:'libraries', params: {libraryId: LIBRARIES_ALL}}">
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-book-multiple</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
|
@ -51,7 +51,7 @@
|
|||
<v-list-item v-for="(l, index) in libraries"
|
||||
:key="index"
|
||||
dense
|
||||
:to="{name:'browse-libraries', params: {libraryId: l.id}}"
|
||||
:to="{name:'libraries', params: {libraryId: l.id}}"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
</v-list-item-icon>
|
||||
|
|
@ -158,12 +158,14 @@ import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
|||
import SearchBox from '@/components/SearchBox.vue'
|
||||
import {Theme} from '@/types/themes'
|
||||
import Vue from 'vue'
|
||||
import {LIBRARIES_ALL} from "@/types/library";
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'home',
|
||||
components: {LibraryActionsMenu, SearchBox, Dialogs},
|
||||
data: function () {
|
||||
return {
|
||||
LIBRARIES_ALL,
|
||||
drawerVisible: this.$vuetify.breakpoint.lgAndUp,
|
||||
info: {} as ActuatorInfo,
|
||||
locales: this.$i18n.availableLocales.map((x: any) => ({text: this.$i18n.t('common.locale_name', x), value: x})),
|
||||
|
|
|
|||
|
|
@ -144,14 +144,12 @@ class BookDtoDao(
|
|||
): BookDto? =
|
||||
findSiblingReadList(readListId, bookId, userId, filterOnLibraryIds, next = true)
|
||||
|
||||
override fun findOnDeck(libraryIds: Collection<String>, userId: String, pageable: Pageable): Page<BookDto> {
|
||||
val conditions = if (libraryIds.isEmpty()) DSL.trueCondition() else s.LIBRARY_ID.`in`(libraryIds)
|
||||
|
||||
override fun findOnDeck(userId: String, filterOnLibraryIds: Collection<String>?, pageable: Pageable): Page<BookDto> {
|
||||
val seriesIds = dsl.select(s.ID)
|
||||
.from(s)
|
||||
.leftJoin(b).on(s.ID.eq(b.SERIES_ID))
|
||||
.leftJoin(r).on(b.ID.eq(r.BOOK_ID)).and(readProgressCondition(userId))
|
||||
.where(conditions)
|
||||
.apply { filterOnLibraryIds?.let { where(s.LIBRARY_ID.`in`(it)) } }
|
||||
.groupBy(s.ID)
|
||||
.having(SeriesDtoDao.countUnread.ge(inline(1.toBigDecimal())))
|
||||
.and(SeriesDtoDao.countRead.ge(inline(1.toBigDecimal())))
|
||||
|
|
|
|||
|
|
@ -153,16 +153,14 @@ class BookController(
|
|||
@GetMapping("api/v1/books/ondeck")
|
||||
fun getBooksOnDeck(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@RequestParam(name = "library_id", required = false) libraryIds: List<String>?,
|
||||
@Parameter(hidden = true) page: Pageable
|
||||
): Page<BookDto> {
|
||||
val libraryIds = if (principal.user.sharedAllLibraries) emptySet() else principal.user.sharedLibrariesIds
|
||||
|
||||
return bookDtoRepository.findOnDeck(
|
||||
libraryIds,
|
||||
): Page<BookDto> =
|
||||
bookDtoRepository.findOnDeck(
|
||||
principal.user.id,
|
||||
principal.user.getAuthorizedLibraryIds(libraryIds),
|
||||
page
|
||||
).map { it.restrictUrl(!principal.user.roleAdmin) }
|
||||
}
|
||||
|
||||
@GetMapping("api/v1/books/{bookId}")
|
||||
fun getOneBook(
|
||||
|
|
@ -289,7 +287,10 @@ class BookController(
|
|||
val media = mediaRepository.findById(book.id)
|
||||
when (media.status) {
|
||||
Media.Status.UNKNOWN -> throw ResponseStatusException(HttpStatus.NOT_FOUND, "Book has not been analyzed yet")
|
||||
Media.Status.OUTDATED -> throw ResponseStatusException(HttpStatus.NOT_FOUND, "Book is outdated and must be re-analyzed")
|
||||
Media.Status.OUTDATED -> throw ResponseStatusException(
|
||||
HttpStatus.NOT_FOUND,
|
||||
"Book is outdated and must be re-analyzed"
|
||||
)
|
||||
Media.Status.ERROR -> throw ResponseStatusException(HttpStatus.NOT_FOUND, "Book analysis failed")
|
||||
Media.Status.UNSUPPORTED -> throw ResponseStatusException(HttpStatus.NOT_FOUND, "Book format is not supported")
|
||||
Media.Status.READY -> media.pages.mapIndexed { index, s ->
|
||||
|
|
@ -319,7 +320,10 @@ class BookController(
|
|||
request: WebRequest,
|
||||
@PathVariable bookId: String,
|
||||
@PathVariable pageNumber: Int,
|
||||
@Parameter(description = "Convert the image to the provided format.", schema = Schema(allowableValues = ["jpeg", "png"]))
|
||||
@Parameter(
|
||||
description = "Convert the image to the provided format.",
|
||||
schema = Schema(allowableValues = ["jpeg", "png"])
|
||||
)
|
||||
@RequestParam(value = "convert", required = false) convertTo: String?,
|
||||
@Parameter(description = "If set to true, pages will start at index 0. If set to false, pages will start at index 1.")
|
||||
@RequestParam(value = "zero_based", defaultValue = "false") zeroBasedIndex: Boolean
|
||||
|
|
|
|||
|
|
@ -37,5 +37,5 @@ interface BookDtoRepository {
|
|||
filterOnLibraryIds: Collection<String>?
|
||||
): BookDto?
|
||||
|
||||
fun findOnDeck(libraryIds: Collection<String>, userId: String, pageable: Pageable): Page<BookDto>
|
||||
fun findOnDeck(userId: String, filterOnLibraryIds: Collection<String>?, pageable: Pageable): Page<BookDto>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -231,8 +231,8 @@ class BookDtoDaoTest(
|
|||
|
||||
// when
|
||||
val found = bookDtoDao.findOnDeck(
|
||||
emptyList(),
|
||||
user.id,
|
||||
null,
|
||||
PageRequest.of(0, 20)
|
||||
)
|
||||
|
||||
|
|
@ -252,8 +252,8 @@ class BookDtoDaoTest(
|
|||
|
||||
// when
|
||||
val found = bookDtoDao.findOnDeck(
|
||||
emptyList(),
|
||||
user.id,
|
||||
null,
|
||||
PageRequest.of(0, 20)
|
||||
)
|
||||
|
||||
|
|
@ -276,8 +276,8 @@ class BookDtoDaoTest(
|
|||
|
||||
// when
|
||||
val found = bookDtoDao.findOnDeck(
|
||||
emptyList(),
|
||||
user.id,
|
||||
null,
|
||||
PageRequest.of(0, 20)
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue