mirror of
https://github.com/gotson/komga.git
synced 2025-01-09 04:08:00 +08:00
feat: Added a 'Recommended' tab in the library views for a library specific dashboard like the home page
This commit is contained in:
parent
3834d415ae
commit
b26559dc47
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<v-bottom-navigation
|
||||
v-if="collectionsCount > 0 || readListsCount > 0"
|
||||
grow color="primary"
|
||||
:fixed="$vuetify.breakpoint.name === 'xs'"
|
||||
>
|
||||
@ -9,6 +8,11 @@
|
||||
<v-icon>mdi-bookshelf</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn :to="{name: 'recommended-libraries', params: {libraryId: libraryId}}">
|
||||
<span>{{ $t('library_navigation.recommended') }}</span>
|
||||
<v-icon>mdi-view-dashboard</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn
|
||||
v-if="collectionsCount > 0"
|
||||
:to="{name: 'browse-collections', params: {libraryId: libraryId}}"
|
||||
|
@ -417,7 +417,8 @@
|
||||
"library_navigation": {
|
||||
"browse": "Browse",
|
||||
"collections": "Collections",
|
||||
"readlists": "Read Lists"
|
||||
"readlists": "Read Lists",
|
||||
"recommended": "Recommended"
|
||||
},
|
||||
"login": {
|
||||
"create_user_account": "Create user account",
|
||||
|
@ -90,6 +90,13 @@ const router = new Router({
|
||||
component: () => import(/* webpackChunkName: "browse-libraries" */ './views/BrowseLibraries.vue'),
|
||||
props: (route) => ({ libraryId: route.params.libraryId }),
|
||||
},
|
||||
{
|
||||
path: '/libraries/:libraryId/dashboard',
|
||||
name: 'recommended-libraries',
|
||||
beforeEnter: noLibraryGuard,
|
||||
component: () => import(/* webpackChunkName: "dashboard" */ './views/Dashboard.vue'),
|
||||
props: (route) => ({ libraryId: route.params.libraryId }),
|
||||
},
|
||||
{
|
||||
path: '/libraries/:libraryId/collections',
|
||||
name: 'browse-collections',
|
||||
|
@ -1,5 +1,25 @@
|
||||
<template>
|
||||
<div>
|
||||
<div :style="libraryId && $vuetify.breakpoint.name === 'xs' ? 'margin-bottom: 56px' : undefined">
|
||||
<div v-if="libraryId">
|
||||
<toolbar-sticky v-if="selectedSeries.length === 0">
|
||||
|
||||
<library-actions-menu
|
||||
v-if="library"
|
||||
:library="library"
|
||||
/>
|
||||
|
||||
<v-toolbar-title>
|
||||
<span>{{ library ? library.name : $t('common.all_libraries') }}</span>
|
||||
<v-chip label class="mx-4" v-if="totalElements">
|
||||
<span style="font-size: 1.1rem">{{ totalElements }}</span>
|
||||
</v-chip>
|
||||
</v-toolbar-title>
|
||||
|
||||
</toolbar-sticky>
|
||||
|
||||
<library-navigation :libraryId="libraryId"/>
|
||||
</div>
|
||||
|
||||
<series-multi-select-bar
|
||||
v-model="selectedSeries"
|
||||
@unselect-all="selectedSeries = []"
|
||||
@ -110,6 +130,9 @@ 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'
|
||||
@ -121,12 +144,16 @@ export default Vue.extend({
|
||||
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[],
|
||||
@ -149,6 +176,11 @@ export default Vue.extend({
|
||||
mounted () {
|
||||
this.loadAll()
|
||||
},
|
||||
props: {
|
||||
libraryId: {
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedSeries (val: SeriesDto[]) {
|
||||
val.forEach(i => this.replaceSeries(i))
|
||||
@ -156,6 +188,9 @@ export default Vue.extend({
|
||||
selectedBooks (val: BookDto[]) {
|
||||
val.forEach(i => this.replaceBook(i))
|
||||
},
|
||||
'$route.path': function(val, oldVal){
|
||||
this.loadAll()
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
fixedCardWidth (): number {
|
||||
@ -178,6 +213,9 @@ export default Vue.extend({
|
||||
}
|
||||
},
|
||||
loadAll () {
|
||||
if(this.libraryId){
|
||||
this.loadLibrary(this.libraryId)
|
||||
}
|
||||
this.selectedSeries = []
|
||||
this.selectedBooks = []
|
||||
this.loadNewSeries()
|
||||
@ -211,14 +249,21 @@ export default Vue.extend({
|
||||
}
|
||||
},
|
||||
async loadNewSeries () {
|
||||
this.newSeries = (await this.$komgaSeries.getNewSeries()).content
|
||||
const pageRequest = {
|
||||
library_id: this.libraryId,
|
||||
} as PageRequest
|
||||
this.newSeries = (await this.$komgaSeries.getNewSeries(pageRequest)).content
|
||||
},
|
||||
async loadUpdatedSeries () {
|
||||
this.updatedSeries = (await this.$komgaSeries.getUpdatedSeries()).content
|
||||
const pageRequest = {
|
||||
library_id: this.libraryId,
|
||||
} as PageRequest
|
||||
this.updatedSeries = (await this.$komgaSeries.getUpdatedSeries(pageRequest)).content
|
||||
},
|
||||
async loadLatestBooks () {
|
||||
const pageRequest = {
|
||||
sort: ['createdDate,desc'],
|
||||
library_id: this.libraryId,
|
||||
} as PageRequest
|
||||
|
||||
this.latestBooks = (await this.$komgaBooks.getBooks(undefined, pageRequest)).content
|
||||
@ -226,12 +271,17 @@ export default Vue.extend({
|
||||
async loadInProgressBooks () {
|
||||
const pageRequest = {
|
||||
sort: ['readProgress.lastModified,desc'],
|
||||
library_id: this.libraryId,
|
||||
} as PageRequest
|
||||
|
||||
this.inProgressBooks = (await this.$komgaBooks.getBooks(undefined, pageRequest, undefined, undefined, [ReadStatus.IN_PROGRESS])).content
|
||||
},
|
||||
async loadOnDeckBooks () {
|
||||
this.onDeckBooks = (await this.$komgaBooks.getBooksOnDeck()).content
|
||||
const pageRequest = {
|
||||
library_id: this.libraryId,
|
||||
} as PageRequest
|
||||
|
||||
this.onDeckBooks = (await this.$komgaBooks.getBooksOnDeck(pageRequest)).content
|
||||
},
|
||||
singleEditSeries (series: SeriesDto) {
|
||||
this.$store.dispatch('dialogUpdateSeries', series)
|
||||
@ -283,6 +333,11 @@ export default Vue.extend({
|
||||
this.$komgaBooks.getBook(b.id),
|
||||
))
|
||||
},
|
||||
loadLibrary(libraryId: string) {
|
||||
if (libraryId) {
|
||||
this.library = this.$store.getters.getLibraryById(libraryId)
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
@ -5972,6 +5972,14 @@
|
||||
"in": "query",
|
||||
"name": "size",
|
||||
"description": "The size of the page to be returned"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "library_id",
|
||||
"required": false
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
@ -6188,4 +6196,4 @@
|
||||
"title": "Komga API",
|
||||
"version": "v1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,13 +147,18 @@ class BookController(
|
||||
}
|
||||
|
||||
@Operation(description = "Return first unread book of series with at least one book read and no books in progress.")
|
||||
@PageableWithoutSortAsQueryParam
|
||||
@PageableAsQueryParam
|
||||
@GetMapping("api/v1/books/ondeck")
|
||||
fun getBooksOnDeck(
|
||||
@AuthenticationPrincipal principal: KomgaPrincipal,
|
||||
@RequestParam(name = "library_id", required = false) libraryId: List<String>?,
|
||||
@Parameter(hidden = true) page: Pageable
|
||||
): Page<BookDto> {
|
||||
val libraryIds = if (principal.user.sharedAllLibraries) emptySet() else principal.user.sharedLibrariesIds
|
||||
val libraryIds = when {
|
||||
!libraryId.isNullOrEmpty() -> libraryId
|
||||
principal.user.sharedAllLibraries -> emptySet()
|
||||
else -> principal.user.sharedLibrariesIds
|
||||
}
|
||||
|
||||
return bookDtoRepository.findOnDeck(
|
||||
libraryIds,
|
||||
|
Loading…
Reference in New Issue
Block a user