feat(webui): add ability to configure recommended view per library

Closes: #1539
This commit is contained in:
Gauthier Roebroeck 2025-02-10 18:03:30 +08:00
parent 6c71e07a27
commit e980e3316e
6 changed files with 394 additions and 193 deletions

View file

@ -73,7 +73,6 @@ export default Vue.extend({
dragOptions(): any {
return {
animation: 200,
// group: 'item-cards',
ghostClass: 'ghost',
}
},

View file

@ -0,0 +1,135 @@
<template>
<v-dialog v-model="modal"
max-width="450"
>
<v-card>
<v-card-title>{{ $t('dialog.edit_recommended.dialog_title') }}</v-card-title>
<v-btn icon absolute top right @click="dialogClose">
<v-icon>mdi-close</v-icon>
</v-btn>
<v-card-text>
<v-list>
<draggable
v-model="localItems"
v-bind="dragOptions"
handle=".handle"
>
<v-list-item v-for="(l, index) in localItems" :key="index">
<v-list-item-icon>
<v-icon class="handle">mdi-drag-horizontal-variant</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title class="handle">{{ $t(`dashboard.${l.section.toLowerCase()}`) }}</v-list-item-title>
</v-list-item-content>
<v-list-item-action>
<v-switch v-model="enabled[l.section]"/>
</v-list-item-action>
</v-list-item>
</draggable>
</v-list>
</v-card-text>
<v-card-actions>
<v-spacer/>
<v-btn text @click="dialogClose">{{ $t('common.cancel') }}</v-btn>
<v-btn color="error" @click="resetToDefault">{{
$t('dialog.edit_recommended.button_reset')
}}
</v-btn>
<v-btn color="primary" @click="saveChanges">{{
$t('dialog.edit_recommended.button_confirm')
}}
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script lang="ts">
import {UserRoles} from '@/types/enum-users'
import draggable from 'vuedraggable'
import Vue, {PropType} from 'vue'
import {
ClientSettingsRecommendedView,
ClientSettingsRecommendedViewSection,
RECOMMENDED_DEFAULT,
} from '@/types/komga-clientsettings'
export default Vue.extend({
name: 'EditRecommendedDialog',
components: {draggable},
data: function () {
return {
UserRoles,
modal: false,
localItems: [] as ClientSettingsRecommendedViewSection[],
enabled: {} as Record<string, boolean>,
}
},
props: {
value: Boolean,
viewConfig: {
type: Object as PropType<ClientSettingsRecommendedView>,
required: true,
},
},
watch: {
value(val) {
this.modal = val
if (val) {
this.reset(this.viewConfig)
}
},
modal(val) {
!val && this.dialogClose()
},
},
computed: {
dragOptions(): any {
return {
animation: 200,
ghostClass: 'ghost',
}
},
},
methods: {
reset(viewConfig: ClientSettingsRecommendedView) {
this.localItems = viewConfig?.sections || []
this.enabled = []
this.localItems.forEach(it => this.enabled[it.section] = true)
RECOMMENDED_DEFAULT.sections
.filter(it => !viewConfig?.sections.some(s => s.section === it.section))
.forEach(it => this.localItems.push(it))
},
dialogClose() {
this.$emit('input', false)
},
resetToDefault() {
this.$emit('reset-defaults')
this.dialogClose()
},
saveChanges() {
const sections = this.localItems.filter(it => this.enabled[it.section])
const updated = {
sections: sections,
} as ClientSettingsRecommendedView
this.$emit('update:viewConfig', updated)
this.dialogClose()
},
},
})
</script>
<style scoped>
.handle {
cursor: grab !important;
}
.ghost {
opacity: 0.5;
background: #c8ebfb;
}
</style>

View file

@ -516,6 +516,11 @@
"tab_general": "General",
"tab_poster": "Poster"
},
"edit_recommended": {
"button_confirm": "Save changes",
"button_reset": "Reset to default",
"dialog_title": "Edit recommended view"
},
"edit_series": {
"button_cancel": "Cancel",
"button_confirm": "Save changes",

View file

@ -83,4 +83,16 @@ export default class KomgaSettingsService {
throw new Error(msg)
}
}
async deleteClientSettingUser(settings: string[]) {
try {
await this.http.delete(`${API_CLIENT_SETTINGS}/user`, {data: settings})
} catch (e) {
let msg = 'An error occurred while trying to delete user client setting'
if (e.response.data.message) {
msg += `: ${e.response.data.message}`
}
throw new Error(msg)
}
}
}

View file

@ -19,6 +19,7 @@ export enum CLIENT_SETTING {
WEBUI_POSTER_BLUR_UNREAD = 'webui.poster.blur_unread',
WEBUI_LIBRARIES = 'webui.libraries',
WEBUI_SERIES_GROUPS = 'webui.series_groups',
WEBUI_RECOMMENDED = 'webui.recommended',
}
export interface ClientSettingLibrary {
@ -112,3 +113,33 @@ export const SERIES_GROUP_JAPANESE = {
'わ': ['わ', 'ワ'],
},
} as ClientSettingsSeriesGroup
export interface ClientSettingsRecommendedView {
sections: ClientSettingsRecommendedViewSection[],
}
export interface ClientSettingsRecommendedViewSection {
section: RecommendedViewSection,
}
export enum RecommendedViewSection {
KEEP_READING = 'KEEP_READING',
ON_DECK = 'ON_DECK',
RECENTLY_RELEASED_BOOKS = 'RECENTLY_RELEASED_BOOKS',
RECENTLY_ADDED_BOOKS = 'RECENTLY_ADDED_BOOKS',
RECENTLY_ADDED_SERIES = 'RECENTLY_ADDED_SERIES',
RECENTLY_UPDATED_SERIES = 'RECENTLY_UPDATED_SERIES',
RECENTLY_READ_BOOKS = 'RECENTLY_READ_BOOKS',
}
export const RECOMMENDED_DEFAULT = {
sections: [
{section: RecommendedViewSection.KEEP_READING},
{section: RecommendedViewSection.ON_DECK},
{section: RecommendedViewSection.RECENTLY_RELEASED_BOOKS},
{section: RecommendedViewSection.RECENTLY_ADDED_BOOKS},
{section: RecommendedViewSection.RECENTLY_ADDED_SERIES},
{section: RecommendedViewSection.RECENTLY_UPDATED_SERIES},
{section: RecommendedViewSection.RECENTLY_READ_BOOKS},
],
} as ClientSettingsRecommendedView

View file

@ -54,150 +54,57 @@
>
</empty-state>
<horizontal-scroller
v-if="loaderInProgressBooks && loaderInProgressBooks.items.length !== 0"
class="mb-4"
:tick="loaderInProgressBooks.tick"
@scroll-changed="(percent) => scrollChanged(loaderInProgressBooks, percent)"
>
<template v-slot:prepend>
<div class="title">{{ $t('dashboard.keep_reading') }}</div>
</template>
<template v-slot:content>
<item-browser :items="loaderInProgressBooks.items"
:item-context="[ItemContext.SHOW_SERIES]"
nowrap
:edit-function="isAdmin ? singleEditBook : undefined"
:selected.sync="selectedBooks"
:selectable="selectedSeries.length === 0"
:fixed-item-width="fixedCardWidth"
/>
</template>
</horizontal-scroller>
<template v-for="(section, i) in sections">
<horizontal-scroller
v-bind:key="i"
v-if="section.loader && section.loader.items.length !== 0"
class="mb-4"
:tick="section.loader.tick"
@scroll-changed="(percent) => scrollChanged(section.loader, percent)"
>
<template v-slot:prepend>
<div class="title">{{ $t(`dashboard.${section.value.toLowerCase()}`) }}</div>
</template>
<template v-slot:content>
<item-browser v-if="section.type ===SectionType.BOOK"
:items="section.loader.items"
:item-context="section.itemContext"
nowrap
:edit-function="isAdmin ? singleEditBook : undefined"
:selected.sync="selectedBooks"
:selectable="selectedSeries.length === 0"
:fixed-item-width="fixedCardWidth"
/>
<item-browser v-if="section.type === SectionType.SERIES"
:items="section.loader.items"
:item-context="section.itemContext"
nowrap
:edit-function="isAdmin ? singleEditSeries : undefined"
:selected.sync="selectedSeries"
:selectable="selectedBooks.length === 0"
:fixed-item-width="fixedCardWidth"
/>
</template>
</horizontal-scroller>
</template>
<horizontal-scroller
v-if="loaderOnDeckBooks && loaderOnDeckBooks.items.length !== 0"
class="mb-4"
:tick="loaderOnDeckBooks.tick"
@scroll-changed="(percent) => scrollChanged(loaderOnDeckBooks, percent)"
>
<template v-slot:prepend>
<div class="title">{{ $t('dashboard.on_deck') }}</div>
</template>
<template v-slot:content>
<item-browser :items="loaderOnDeckBooks.items"
:item-context="[ItemContext.SHOW_SERIES]"
nowrap
:edit-function="isAdmin ? singleEditBook : undefined"
:selected.sync="selectedBooks"
:selectable="selectedSeries.length === 0"
:fixed-item-width="fixedCardWidth"
/>
</template>
</horizontal-scroller>
<v-fab-transition>
<v-btn
fab
bottom
right
fixed
@click="modalEditRecommended = true"
>
<v-icon>mdi-pencil</v-icon>
</v-btn>
</v-fab-transition>
<horizontal-scroller
v-if="loaderRecentlyReleasedBooks && loaderRecentlyReleasedBooks.items.length !== 0"
class="mb-4"
:tick="loaderRecentlyReleasedBooks.tick"
@scroll-changed="(percent) => scrollChanged(loaderRecentlyReleasedBooks, percent)"
>
<template v-slot:prepend>
<div class="title">{{ $t('dashboard.recently_released_books') }}</div>
</template>
<template v-slot:content>
<item-browser :items="loaderRecentlyReleasedBooks.items"
:item-context="[ItemContext.RELEASE_DATE, ItemContext.SHOW_SERIES]"
nowrap
:edit-function="isAdmin ? singleEditBook : undefined"
:selected.sync="selectedBooks"
:selectable="selectedSeries.length === 0"
:fixed-item-width="fixedCardWidth"
/>
</template>
</horizontal-scroller>
<horizontal-scroller
v-if="loaderLatestBooks && loaderLatestBooks.items.length !== 0"
class="mb-4"
:tick="loaderLatestBooks.tick"
@scroll-changed="(percent) => scrollChanged(loaderLatestBooks, percent)"
>
<template v-slot:prepend>
<div class="title">{{ $t('dashboard.recently_added_books') }}</div>
</template>
<template v-slot:content>
<item-browser :items="loaderLatestBooks.items"
:item-context="[ItemContext.SHOW_SERIES]"
nowrap
:edit-function="isAdmin ? singleEditBook : undefined"
:selected.sync="selectedBooks"
:selectable="selectedSeries.length === 0"
:fixed-item-width="fixedCardWidth"
/>
</template>
</horizontal-scroller>
<horizontal-scroller
v-if="loaderNewSeries && loaderNewSeries.items.length !== 0"
class="mb-4"
:tick="loaderNewSeries.tick"
@scroll-changed="(percent) => scrollChanged(loaderNewSeries, percent)"
>
<template v-slot:prepend>
<div class="title">{{ $t('dashboard.recently_added_series') }}</div>
</template>
<template v-slot:content>
<item-browser :items="loaderNewSeries.items"
nowrap
:edit-function="isAdmin ? singleEditSeries : undefined"
:selected.sync="selectedSeries"
:selectable="selectedBooks.length === 0"
:fixed-item-width="fixedCardWidth"
/>
</template>
</horizontal-scroller>
<horizontal-scroller
v-if="loaderUpdatedSeries && loaderUpdatedSeries.items.length !== 0"
class="mb-4"
:tick="loaderUpdatedSeries.tick"
@scroll-changed="(percent) => scrollChanged(loaderUpdatedSeries, percent)"
>
<template v-slot:prepend>
<div class="title">{{ $t('dashboard.recently_updated_series') }}</div>
</template>
<template v-slot:content>
<item-browser :items="loaderUpdatedSeries.items"
nowrap
:edit-function="isAdmin ? singleEditSeries : undefined"
:selected.sync="selectedSeries"
:selectable="selectedBooks.length === 0"
:fixed-item-width="fixedCardWidth"
/>
</template>
</horizontal-scroller>
<horizontal-scroller
v-if="loaderRecentlyReadBooks && loaderRecentlyReadBooks.items.length !== 0"
class="mb-4"
:tick="loaderRecentlyReadBooks.tick"
@scroll-changed="(percent) => scrollChanged(loaderRecentlyReadBooks, percent)"
>
<template v-slot:prepend>
<div class="title">{{ $t('dashboard.recently_read_books') }}</div>
</template>
<template v-slot:content>
<item-browser :items="loaderRecentlyReadBooks.items"
:item-context="[ItemContext.SHOW_SERIES, ItemContext.READ_DATE]"
nowrap
:edit-function="isAdmin ? singleEditBook : undefined"
:selected.sync="selectedBooks"
:selectable="selectedSeries.length === 0"
:fixed-item-width="fixedCardWidth"
/>
</template>
</horizontal-scroller>
<edit-recommended-dialog
v-model="modalEditRecommended"
:view-config.sync="viewConfig"
@reset-defaults="resetDefaultView"
/>
</v-container>
</div>
</template>
@ -246,10 +153,32 @@ import {
SearchOperatorAfter,
SearchOperatorIs,
} from '@/types/komga-search'
import {
CLIENT_SETTING,
ClientSettingsRecommendedView,
ClientSettingsRecommendedViewSection,
ClientSettingUserUpdateDto,
RECOMMENDED_DEFAULT,
RecommendedViewSection,
} from '@/types/komga-clientsettings'
import EditRecommendedDialog from '@/components/dialogs/EditRecommendedDialog.vue'
interface SectionConfig {
loader: PageLoader<any> | undefined,
type: SectionType,
value: RecommendedViewSection,
itemContext?: ItemContext[] | undefined,
}
enum SectionType {
SERIES,
BOOK,
}
export default Vue.extend({
name: 'DashboardView',
components: {
EditRecommendedDialog,
HorizontalScroller,
EmptyState,
ToolbarSticky,
@ -261,14 +190,16 @@ export default Vue.extend({
data: () => {
return {
ItemContext,
SectionType,
loading: false,
loaderNewSeries: undefined as unknown as PageLoader<SeriesDto>,
loaderUpdatedSeries: undefined as unknown as PageLoader<SeriesDto>,
loaderLatestBooks: undefined as unknown as PageLoader<BookDto>,
loaderInProgressBooks: undefined as unknown as PageLoader<BookDto>,
loaderOnDeckBooks: undefined as unknown as PageLoader<BookDto>,
loaderRecentlyReleasedBooks: undefined as unknown as PageLoader<BookDto>,
loaderRecentlyReadBooks: undefined as unknown as PageLoader<BookDto>,
modalEditRecommended: false,
loaderRecentlyAddedSeries: undefined as PageLoader<SeriesDto> | undefined,
loaderRecentlyUpdatedSeries: undefined as PageLoader<SeriesDto> | undefined,
loaderRecentlyAddedBooks: undefined as PageLoader<BookDto> | undefined,
loaderKeepReadingBooks: undefined as PageLoader<BookDto> | undefined,
loaderOnDeckBooks: undefined as PageLoader<BookDto> | undefined,
loaderRecentlyReleasedBooks: undefined as PageLoader<BookDto> | undefined,
loaderRecentlyReadBooks: undefined as PageLoader<BookDto> | undefined,
selectedSeries: [] as SeriesDto[],
selectedBooks: [] as BookDto[],
}
@ -312,10 +243,6 @@ export default Vue.extend({
},
},
watch: {
libraryId(val) {
this.setupLoaders(val)
this.loadAll()
},
libraryIds() {
this.setupLoaders(this.libraryId)
this.loadAll()
@ -333,6 +260,36 @@ export default Vue.extend({
},
},
computed: {
settingsKey(): string {
return `${CLIENT_SETTING.WEBUI_RECOMMENDED}.${this.libraryId}`.toLowerCase()
},
viewConfig: {
get: function (): ClientSettingsRecommendedView {
try {
return JSON.parse(this.$store.getters.getClientSettings[this.settingsKey].value) as ClientSettingsRecommendedView
} catch (_) {
}
return RECOMMENDED_DEFAULT
},
set: async function (view: ClientSettingsRecommendedView) {
let newSettings = {} as Record<string, ClientSettingUserUpdateDto>
newSettings[this.settingsKey] = {
value: JSON.stringify(view),
}
await this.$komgaSettings.updateClientSettingUser(newSettings)
await this.$store.dispatch('getClientSettingsUser')
this.setupLoaders(this.libraryId)
this.loadAll(true)
},
},
sections(): SectionConfig[] {
const sections = [] as SectionConfig[]
this.viewConfig.sections.forEach((it: ClientSettingsRecommendedViewSection) => {
const config = this.getSectionConfig(it.section)
if (config != undefined) sections.push(config)
})
return sections
},
library(): LibraryDto | undefined {
return this.getLibraryLazy(this.libraryId)
},
@ -346,13 +303,13 @@ export default Vue.extend({
return this.$vuetify.breakpoint.xs ? 120 : 150
},
allEmpty(): boolean {
return this.loaderNewSeries?.items.length === 0 &&
this.loaderUpdatedSeries?.items.length === 0 &&
this.loaderLatestBooks?.items.length === 0 &&
this.loaderInProgressBooks?.items.length === 0 &&
this.loaderOnDeckBooks?.items.length === 0 &&
this.loaderRecentlyReleasedBooks?.items.length === 0 &&
this.loaderRecentlyReadBooks?.items.length === 0
return (this.loaderRecentlyAddedSeries == undefined || this.loaderRecentlyAddedSeries?.items.length === 0) &&
(this.loaderRecentlyUpdatedSeries == undefined || this.loaderRecentlyUpdatedSeries?.items.length === 0) &&
(this.loaderRecentlyAddedBooks == undefined || this.loaderRecentlyAddedBooks?.items.length === 0) &&
(this.loaderKeepReadingBooks == undefined || this.loaderKeepReadingBooks?.items.length === 0) &&
(this.loaderOnDeckBooks == undefined || this.loaderOnDeckBooks?.items.length === 0) &&
(this.loaderRecentlyReleasedBooks == undefined || this.loaderRecentlyReleasedBooks?.items.length === 0) &&
(this.loaderRecentlyReadBooks == undefined || this.loaderRecentlyReadBooks?.items.length === 0)
},
individualLibrary(): boolean {
return this.libraryId !== LIBRARIES_ALL
@ -362,6 +319,68 @@ export default Vue.extend({
},
},
methods: {
async resetDefaultView() {
await this.$komgaSettings.deleteClientSettingUser([this.settingsKey])
await this.$store.dispatch('getClientSettingsUser')
this.setupLoaders(this.libraryId)
this.loadAll(true)
},
hasSection(section: RecommendedViewSection): boolean {
return this.viewConfig.sections.some(it => it.section === section)
},
getSectionConfig(section: RecommendedViewSection): SectionConfig | undefined {
switch (section) {
case RecommendedViewSection.KEEP_READING:
return {
loader: this.loaderKeepReadingBooks,
type: SectionType.BOOK,
value: section,
itemContext: [ItemContext.SHOW_SERIES],
}
case RecommendedViewSection.ON_DECK:
return {
loader: this.loaderOnDeckBooks,
type: SectionType.BOOK,
value: section,
itemContext: [ItemContext.SHOW_SERIES],
}
case RecommendedViewSection.RECENTLY_RELEASED_BOOKS:
return {
loader: this.loaderRecentlyReleasedBooks,
type: SectionType.BOOK,
value: section,
itemContext: [ItemContext.RELEASE_DATE, ItemContext.SHOW_SERIES],
}
case RecommendedViewSection.RECENTLY_ADDED_BOOKS:
return {
loader: this.loaderRecentlyAddedBooks,
type: SectionType.BOOK,
value: section,
itemContext: [ItemContext.SHOW_SERIES],
}
case RecommendedViewSection.RECENTLY_ADDED_SERIES:
return {
loader: this.loaderRecentlyAddedSeries,
type: SectionType.SERIES,
value: section,
}
case RecommendedViewSection.RECENTLY_UPDATED_SERIES:
return {
loader: this.loaderRecentlyUpdatedSeries,
type: SectionType.SERIES,
value: section,
}
case RecommendedViewSection.RECENTLY_READ_BOOKS:
return {
loader: this.loaderRecentlyReadBooks,
type: SectionType.BOOK,
value: section,
itemContext: [ItemContext.SHOW_SERIES],
}
default:
return undefined
}
},
async scrollChanged(loader: PageLoader<any>, percent: number) {
if (percent > 0.95) await loader.loadNext()
},
@ -379,15 +398,15 @@ export default Vue.extend({
}
},
readProgressChanged(event: ReadProgressSseDto) {
if (this.loaderInProgressBooks?.items.some(b => b.id === event.bookId)) this.reload()
else if (this.loaderLatestBooks?.items.some(b => b.id === event.bookId)) this.reload()
if (this.loaderKeepReadingBooks?.items.some(b => b.id === event.bookId)) this.reload()
else if (this.loaderRecentlyAddedBooks?.items.some(b => b.id === event.bookId)) this.reload()
else if (this.loaderOnDeckBooks?.items.some(b => b.id === event.bookId)) this.reload()
else if (this.loaderRecentlyReleasedBooks?.items.some(b => b.id === event.bookId)) this.reload()
else if (this.loaderRecentlyReadBooks?.items.some(b => b.id === event.bookId)) this.reload()
},
readProgressSeriesChanged(event: ReadProgressSeriesSseDto) {
if (this.loaderUpdatedSeries?.items.some(s => s.id === event.seriesId)) this.reload()
else if (this.loaderNewSeries?.items.some(s => s.id === event.seriesId)) this.reload()
if (this.loaderRecentlyUpdatedSeries?.items.some(s => s.id === event.seriesId)) this.reload()
else if (this.loaderRecentlyAddedSeries?.items.some(s => s.id === event.seriesId)) this.reload()
},
reload: throttle(function (this: any) {
this.loadAll(true)
@ -400,43 +419,43 @@ export default Vue.extend({
requestLibraries.map((it: string) => new SearchConditionLibraryId(new SearchOperatorIs(it))),
))
this.loaderInProgressBooks = new PageLoader<BookDto>(
this.loaderKeepReadingBooks = this.hasSection(RecommendedViewSection.KEEP_READING) ? new PageLoader<BookDto>(
{sort: ['readProgress.readDate,desc']},
(pageable: PageRequest) => this.$komgaBooks.getBooksList({
condition: new SearchConditionAllOfBook([...baseBookConditions, new SearchConditionReadStatus(new SearchOperatorIs(ReadStatus.IN_PROGRESS))]),
} as BookSearch, pageable),
)
this.loaderOnDeckBooks = new PageLoader<BookDto>(
) : undefined
this.loaderOnDeckBooks = this.hasSection(RecommendedViewSection.ON_DECK) ? new PageLoader<BookDto>(
{},
(pageable: PageRequest) => this.$komgaBooks.getBooksOnDeck(requestLibraries, pageable),
)
this.loaderLatestBooks = new PageLoader<BookDto>(
) : undefined
this.loaderRecentlyAddedBooks = this.hasSection(RecommendedViewSection.RECENTLY_ADDED_BOOKS) ? new PageLoader<BookDto>(
{sort: ['createdDate,desc']},
(pageable: PageRequest) => this.$komgaBooks.getBooksList({
condition: new SearchConditionAllOfBook(baseBookConditions),
} as BookSearch, pageable),
)
this.loaderRecentlyReleasedBooks = new PageLoader<BookDto>(
) : undefined
this.loaderRecentlyReleasedBooks = this.hasSection(RecommendedViewSection.RECENTLY_RELEASED_BOOKS) ? new PageLoader<BookDto>(
{sort: ['metadata.releaseDate,desc']},
(pageable: PageRequest) => this.$komgaBooks.getBooksList({
condition: new SearchConditionAllOfBook([...baseBookConditions, new SearchConditionReleaseDate(new SearchOperatorAfter(subMonths(new Date(), 1)))]),
} as BookSearch, pageable),
)
this.loaderRecentlyReadBooks = new PageLoader<BookDto>(
) : undefined
this.loaderRecentlyReadBooks = this.hasSection(RecommendedViewSection.RECENTLY_READ_BOOKS) ? new PageLoader<BookDto>(
{sort: ['readProgress.readDate,desc']},
(pageable: PageRequest) => this.$komgaBooks.getBooksList({
condition: new SearchConditionAllOfBook([...baseBookConditions, new SearchConditionReadStatus(new SearchOperatorIs(ReadStatus.READ))]),
} as BookSearch, pageable),
)
) : undefined
this.loaderNewSeries = new PageLoader<SeriesDto>(
this.loaderRecentlyAddedSeries = this.hasSection(RecommendedViewSection.RECENTLY_ADDED_SERIES) ? new PageLoader<SeriesDto>(
{},
(pageable: PageRequest) => this.$komgaSeries.getNewSeries(requestLibraries, false, pageable),
)
this.loaderUpdatedSeries = new PageLoader<SeriesDto>(
) : undefined
this.loaderRecentlyUpdatedSeries = this.hasSection(RecommendedViewSection.RECENTLY_UPDATED_SERIES) ? new PageLoader<SeriesDto>(
{},
(pageable: PageRequest) => this.$komgaSeries.getUpdatedSeries(requestLibraries, false, pageable),
)
) : undefined
},
loadAll(reload: boolean = false) {
this.loading = true
@ -446,25 +465,25 @@ export default Vue.extend({
if (reload) {
Promise.all([
this.loaderInProgressBooks.reload(),
this.loaderOnDeckBooks.reload(),
this.loaderRecentlyReleasedBooks.reload(),
this.loaderLatestBooks.reload(),
this.loaderNewSeries.reload(),
this.loaderUpdatedSeries.reload(),
this.loaderRecentlyReadBooks.reload(),
this.loaderKeepReadingBooks?.reload(),
this.loaderOnDeckBooks?.reload(),
this.loaderRecentlyReleasedBooks?.reload(),
this.loaderRecentlyAddedBooks?.reload(),
this.loaderRecentlyAddedSeries?.reload(),
this.loaderRecentlyUpdatedSeries?.reload(),
this.loaderRecentlyReadBooks?.reload(),
]).then(() => {
this.loading = false
})
} else {
Promise.all([
this.loaderInProgressBooks.loadNext(),
this.loaderOnDeckBooks.loadNext(),
this.loaderRecentlyReleasedBooks.loadNext(),
this.loaderLatestBooks.loadNext(),
this.loaderNewSeries.loadNext(),
this.loaderUpdatedSeries.loadNext(),
this.loaderRecentlyReadBooks.loadNext(),
this.loaderKeepReadingBooks?.loadNext(),
this.loaderOnDeckBooks?.loadNext(),
this.loaderRecentlyReleasedBooks?.loadNext(),
this.loaderRecentlyAddedBooks?.loadNext(),
this.loaderRecentlyAddedSeries?.loadNext(),
this.loaderRecentlyUpdatedSeries?.loadNext(),
this.loaderRecentlyReadBooks?.loadNext(),
]).then(() => {
this.loading = false
})