mirror of
https://github.com/gotson/komga.git
synced 2026-05-08 12:35:30 +02:00
feat(webui): navigate between books of a readlist
This commit is contained in:
parent
bcfb203f74
commit
88d4342ef5
28 changed files with 170 additions and 18 deletions
|
|
@ -92,6 +92,7 @@ import Vue from 'vue'
|
||||||
import ReadListAddToDialog from '@/components/dialogs/ReadListAddToDialog.vue'
|
import ReadListAddToDialog from '@/components/dialogs/ReadListAddToDialog.vue'
|
||||||
import ReadListDeleteDialog from '@/components/dialogs/ReadListDeleteDialog.vue'
|
import ReadListDeleteDialog from '@/components/dialogs/ReadListDeleteDialog.vue'
|
||||||
import ReadListEditDialog from '@/components/dialogs/ReadListEditDialog.vue'
|
import ReadListEditDialog from '@/components/dialogs/ReadListEditDialog.vue'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'Dialogs',
|
name: 'Dialogs',
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
x-large
|
x-large
|
||||||
color="accent"
|
color="accent"
|
||||||
style="position: absolute; top: 50%; left: 50%; margin-left: -36px; margin-top: -36px"
|
style="position: absolute; top: 50%; left: 50%; margin-left: -36px; margin-top: -36px"
|
||||||
:to="{name: 'read-book', params: { bookId: item.id}}"
|
:to="fabTo"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-book-open-page-variant</v-icon>
|
<v-icon>mdi-book-open-page-variant</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
@ -124,6 +124,7 @@ import { createItem, Item, ItemTypes } from '@/types/items'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { RawLocation } from 'vue-router'
|
import { RawLocation } from 'vue-router'
|
||||||
import ReadListActionsMenu from '@/components/menus/ReadListActionsMenu.vue'
|
import ReadListActionsMenu from '@/components/menus/ReadListActionsMenu.vue'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'ItemCard',
|
name: 'ItemCard',
|
||||||
|
|
@ -232,6 +233,9 @@ export default Vue.extend({
|
||||||
to (): RawLocation {
|
to (): RawLocation {
|
||||||
return this.computedItem.to()
|
return this.computedItem.to()
|
||||||
},
|
},
|
||||||
|
fabTo (): RawLocation {
|
||||||
|
return this.computedItem.fabTo()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onClick () {
|
onClick () {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@
|
||||||
import HorizontalScroller from '@/components/HorizontalScroller.vue'
|
import HorizontalScroller from '@/components/HorizontalScroller.vue'
|
||||||
import ItemBrowser from '@/components/ItemBrowser.vue'
|
import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
|
import { ContextOrigin } from '@/types/context'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'ReadListsExpansionPanels',
|
name: 'ReadListsExpansionPanels',
|
||||||
|
|
@ -62,6 +64,7 @@ export default Vue.extend({
|
||||||
const rlId = this.readLists[val].id
|
const rlId = this.readLists[val].id
|
||||||
if (this.$_.isEmpty(this.readListsContent[val])) {
|
if (this.$_.isEmpty(this.readListsContent[val])) {
|
||||||
const content = (await this.$komgaReadLists.getBooks(rlId, { unpaged: true } as PageRequest)).content
|
const content = (await this.$komgaReadLists.getBooks(rlId, { unpaged: true } as PageRequest)).content
|
||||||
|
content.forEach((x: BookDto) => x.context = { origin: ContextOrigin.READLIST, id: rlId })
|
||||||
this.readListsContent.splice(val, 1, content)
|
this.readListsContent.splice(val, 1, content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@
|
||||||
import { bookThumbnailUrl, collectionThumbnailUrl, readListThumbnailUrl, seriesThumbnailUrl } from '@/functions/urls'
|
import { bookThumbnailUrl, collectionThumbnailUrl, readListThumbnailUrl, seriesThumbnailUrl } from '@/functions/urls'
|
||||||
import { debounce } from 'lodash'
|
import { debounce } from 'lodash'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'SearchBox',
|
name: 'SearchBox',
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,7 @@ import { authorRoles } from '@/types/author-roles'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { helpers, requiredIf } from 'vuelidate/lib/validators'
|
import { helpers, requiredIf } from 'vuelidate/lib/validators'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
|
|
||||||
const validDate = (value: any) => !helpers.req(value) || moment(value, 'YYYY-MM-DD', true).isValid()
|
const validDate = (value: any) => !helpers.req(value) || moment(value, 'YYYY-MM-DD', true).isValid()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'ReadListAddToDialog',
|
name: 'ReadListAddToDialog',
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import { getReadProgress } from '@/functions/book-progress'
|
||||||
import { ReadStatus } from '@/types/enum-books'
|
import { ReadStatus } from '@/types/enum-books'
|
||||||
import { BOOK_CHANGED, bookToEventBookChanged } from '@/types/events'
|
import { BOOK_CHANGED, bookToEventBookChanged } from '@/types/events'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
import { BookDto, ReadProgressUpdateDto } from '@/types/komga-books'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'BookActionsMenu',
|
name: 'BookActionsMenu',
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { ContinuousScaleType } from '@/types/enum-reader'
|
import { ContinuousScaleType } from '@/types/enum-reader'
|
||||||
|
import { PageDtoWithUrl } from '@/types/komga-books'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'ContinuousReader',
|
name: 'ContinuousReader',
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ import Vue from 'vue'
|
||||||
import { ReadingDirection } from '@/types/enum-books'
|
import { ReadingDirection } from '@/types/enum-books'
|
||||||
import { PagedReaderLayout, ScaleType } from '@/types/enum-reader'
|
import { PagedReaderLayout, ScaleType } from '@/types/enum-reader'
|
||||||
import { shortcutsLTR, shortcutsRTL, shortcutsVertical } from '@/functions/shortcuts/paged-reader'
|
import { shortcutsLTR, shortcutsRTL, shortcutsVertical } from '@/functions/shortcuts/paged-reader'
|
||||||
|
import { PageDtoWithUrl } from '@/types/komga-books'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'PagedReader',
|
name: 'PagedReader',
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { get, groupBy, mapKeys, mapValues } from 'lodash'
|
import { get, groupBy, mapKeys, mapValues } from 'lodash'
|
||||||
import { authorRoles } from '@/types/author-roles'
|
import { authorRoles } from '@/types/author-roles'
|
||||||
|
import { AuthorDto } from '@/types/komga-books'
|
||||||
|
|
||||||
// return an object where keys are roles, and values are string[]
|
// return an object where keys are roles, and values are string[]
|
||||||
export function groupAuthorsByRole (authors: AuthorDto[]): any {
|
export function groupAuthorsByRole (authors: AuthorDto[]): any {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { BookFormat } from '@/types/komga-books'
|
||||||
|
|
||||||
export function getBookFormatFromMediaType (mediaType: string): BookFormat {
|
export function getBookFormatFromMediaType (mediaType: string): BookFormat {
|
||||||
switch (mediaType) {
|
switch (mediaType) {
|
||||||
case 'application/x-rar-compressed':
|
case 'application/x-rar-compressed':
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { ReadStatus } from '@/types/enum-books'
|
import { ReadStatus } from '@/types/enum-books'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
|
|
||||||
export function getReadProgress (book: BookDto): ReadStatus {
|
export function getReadProgress (book: BookDto): ReadStatus {
|
||||||
if (book.readProgress?.completed) return ReadStatus.READ
|
if (book.readProgress?.completed) return ReadStatus.READ
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { PageDto } from '@/types/komga-books'
|
||||||
|
|
||||||
export function isPageLandscape (p: PageDto): boolean {
|
export function isPageLandscape (p: PageDto): boolean {
|
||||||
return (p?.width ?? 0) > (p?.height ?? 0)
|
return (p?.width ?? 0) > (p?.height ?? 0)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { AxiosInstance } from 'axios'
|
import { AxiosInstance } from 'axios'
|
||||||
|
import { BookDto, BookMetadataUpdateDto, PageDto, ReadProgressUpdateDto } from '@/types/komga-books'
|
||||||
|
|
||||||
const qs = require('qs')
|
const qs = require('qs')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { AxiosInstance } from 'axios'
|
import { AxiosInstance } from 'axios'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
|
|
||||||
const qs = require('qs')
|
const qs = require('qs')
|
||||||
|
|
||||||
|
|
@ -92,4 +93,28 @@ export default class KomgaReadListsService {
|
||||||
throw new Error(msg)
|
throw new Error(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getBookSiblingNext (readListId: string, bookId: string): Promise<BookDto> {
|
||||||
|
try {
|
||||||
|
return (await this.http.get(`${API_READLISTS}/${readListId}/books/${bookId}/next`)).data
|
||||||
|
} catch (e) {
|
||||||
|
let msg = 'An error occurred while trying to retrieve book'
|
||||||
|
if (e.response.data.message) {
|
||||||
|
msg += `: ${e.response.data.message}`
|
||||||
|
}
|
||||||
|
throw new Error(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getBookSiblingPrevious (readListId: string, bookId: string): Promise<BookDto> {
|
||||||
|
try {
|
||||||
|
return (await this.http.get(`${API_READLISTS}/${readListId}/books/${bookId}/previous`)).data
|
||||||
|
} catch (e) {
|
||||||
|
let msg = 'An error occurred while trying to retrieve book'
|
||||||
|
if (e.response.data.message) {
|
||||||
|
msg += `: ${e.response.data.message}`
|
||||||
|
}
|
||||||
|
throw new Error(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { AxiosInstance } from 'axios'
|
import { AxiosInstance } from 'axios'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
|
|
||||||
const qs = require('qs')
|
const qs = require('qs')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
|
|
|
||||||
9
komga-webui/src/types/context.ts
Normal file
9
komga-webui/src/types/context.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
export enum ContextOrigin {
|
||||||
|
SERIES = 'SERIES',
|
||||||
|
READLIST = 'READLIST'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Context {
|
||||||
|
origin: ContextOrigin,
|
||||||
|
id: string,
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
|
|
||||||
export const BOOK_CHANGED = 'book-changed'
|
export const BOOK_CHANGED = 'book-changed'
|
||||||
export const SERIES_CHANGED = 'series-changed'
|
export const SERIES_CHANGED = 'series-changed'
|
||||||
export const COLLECTION_DELETED = 'collection-deleted'
|
export const COLLECTION_DELETED = 'collection-deleted'
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { bookThumbnailUrl, collectionThumbnailUrl, readListThumbnailUrl, seriesThumbnailUrl } from '@/functions/urls'
|
import { bookThumbnailUrl, collectionThumbnailUrl, readListThumbnailUrl, seriesThumbnailUrl } from '@/functions/urls'
|
||||||
import { RawLocation } from 'vue-router/types/router'
|
import { RawLocation } from 'vue-router/types/router'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
|
|
||||||
function plural (count: number, singular: string, plural: string) {
|
function plural (count: number, singular: string, plural: string) {
|
||||||
return `${count} ${count === 1 ? singular : plural}`
|
return `${count} ${count === 1 ? singular : plural}`
|
||||||
|
|
@ -47,6 +48,8 @@ export abstract class Item<T> {
|
||||||
abstract body (): string
|
abstract body (): string
|
||||||
|
|
||||||
abstract to (): RawLocation
|
abstract to (): RawLocation
|
||||||
|
|
||||||
|
abstract fabTo (): RawLocation
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BookItem extends Item<BookDto> {
|
export class BookItem extends Item<BookDto> {
|
||||||
|
|
@ -69,7 +72,19 @@ export class BookItem extends Item<BookDto> {
|
||||||
}
|
}
|
||||||
|
|
||||||
to (): RawLocation {
|
to (): RawLocation {
|
||||||
return { name: 'browse-book', params: { bookId: this.item.id.toString() } }
|
return {
|
||||||
|
name: 'browse-book',
|
||||||
|
params: { bookId: this.item.id },
|
||||||
|
query: { context: this.item?.context?.origin, contextId: this.item?.context?.id },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fabTo (): RawLocation {
|
||||||
|
return {
|
||||||
|
name: 'read-book',
|
||||||
|
params: { bookId: this.item.id },
|
||||||
|
query: { context: this.item?.context?.origin, contextId: this.item?.context?.id },
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,6 +109,10 @@ export class SeriesItem extends Item<SeriesDto> {
|
||||||
to (): RawLocation {
|
to (): RawLocation {
|
||||||
return { name: 'browse-series', params: { seriesId: this.item.id.toString() } }
|
return { name: 'browse-series', params: { seriesId: this.item.id.toString() } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fabTo (): RawLocation {
|
||||||
|
return undefined as unknown as RawLocation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CollectionItem extends Item<CollectionDto> {
|
export class CollectionItem extends Item<CollectionDto> {
|
||||||
|
|
@ -117,6 +136,10 @@ export class CollectionItem extends Item<CollectionDto> {
|
||||||
to (): RawLocation {
|
to (): RawLocation {
|
||||||
return { name: 'browse-collection', params: { collectionId: this.item.id.toString() } }
|
return { name: 'browse-collection', params: { collectionId: this.item.id.toString() } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fabTo (): RawLocation {
|
||||||
|
return undefined as unknown as RawLocation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ReadListItem extends Item<ReadListDto> {
|
export class ReadListItem extends Item<ReadListDto> {
|
||||||
|
|
@ -140,4 +163,8 @@ export class ReadListItem extends Item<ReadListDto> {
|
||||||
to (): RawLocation {
|
to (): RawLocation {
|
||||||
return { name: 'browse-readlist', params: { readListId: this.item.id.toString() } }
|
return { name: 'browse-readlist', params: { readListId: this.item.id.toString() } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fabTo (): RawLocation {
|
||||||
|
return undefined as unknown as RawLocation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
interface BookDto {
|
import { Context } from '@/types/context'
|
||||||
|
|
||||||
|
export interface BookDto {
|
||||||
id: string,
|
id: string,
|
||||||
seriesId: string,
|
seriesId: string,
|
||||||
libraryId: string,
|
libraryId: string,
|
||||||
|
|
@ -11,16 +13,19 @@ interface BookDto {
|
||||||
media: MediaDto,
|
media: MediaDto,
|
||||||
metadata: BookMetadataDto,
|
metadata: BookMetadataDto,
|
||||||
readProgress?: ReadProgressDto
|
readProgress?: ReadProgressDto
|
||||||
|
|
||||||
|
// custom fields
|
||||||
|
context: Context
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MediaDto {
|
export interface MediaDto {
|
||||||
status: string,
|
status: string,
|
||||||
mediaType: string,
|
mediaType: string,
|
||||||
pagesCount: number,
|
pagesCount: number,
|
||||||
comment: string
|
comment: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PageDto {
|
export interface PageDto {
|
||||||
number: number,
|
number: number,
|
||||||
fileName: string,
|
fileName: string,
|
||||||
mediaType: string,
|
mediaType: string,
|
||||||
|
|
@ -28,7 +33,7 @@ interface PageDto {
|
||||||
height?: number,
|
height?: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PageDtoWithUrl {
|
export interface PageDtoWithUrl {
|
||||||
number: number,
|
number: number,
|
||||||
fileName: string,
|
fileName: string,
|
||||||
mediaType: string,
|
mediaType: string,
|
||||||
|
|
@ -37,7 +42,7 @@ interface PageDtoWithUrl {
|
||||||
url: string,
|
url: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BookMetadataDto {
|
export interface BookMetadataDto {
|
||||||
created: string,
|
created: string,
|
||||||
lastModified: string,
|
lastModified: string,
|
||||||
title: string,
|
title: string,
|
||||||
|
|
@ -56,14 +61,14 @@ interface BookMetadataDto {
|
||||||
tagsLock: boolean
|
tagsLock: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ReadProgressDto {
|
export interface ReadProgressDto {
|
||||||
page: number,
|
page: number,
|
||||||
completed: boolean,
|
completed: boolean,
|
||||||
created: string,
|
created: string,
|
||||||
lastModified: string
|
lastModified: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BookMetadataUpdateDto {
|
export interface BookMetadataUpdateDto {
|
||||||
title?: string,
|
title?: string,
|
||||||
titleLock?: boolean,
|
titleLock?: boolean,
|
||||||
summary?: string,
|
summary?: string,
|
||||||
|
|
@ -80,17 +85,17 @@ interface BookMetadataUpdateDto {
|
||||||
tagsLock?: boolean
|
tagsLock?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AuthorDto {
|
export interface AuthorDto {
|
||||||
name: string,
|
name: string,
|
||||||
role: string
|
role: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ReadProgressUpdateDto {
|
export interface ReadProgressUpdateDto {
|
||||||
page?: number,
|
page?: number,
|
||||||
completed?: boolean
|
completed?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BookFormat {
|
export interface BookFormat {
|
||||||
type: string,
|
type: string,
|
||||||
color: string
|
color: string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -288,6 +288,7 @@ import {
|
||||||
import { shortcutsMenus, shortcutsSettings } from '@/functions/shortcuts/bookreader'
|
import { shortcutsMenus, shortcutsSettings } from '@/functions/shortcuts/bookreader'
|
||||||
import { shortcutsAll } from '@/functions/shortcuts/reader'
|
import { shortcutsAll } from '@/functions/shortcuts/reader'
|
||||||
import { shortcutsSettingsContinuous } from '@/functions/shortcuts/continuous-reader'
|
import { shortcutsSettingsContinuous } from '@/functions/shortcuts/continuous-reader'
|
||||||
|
import { BookDto, PageDto, PageDtoWithUrl } from '@/types/komga-books'
|
||||||
|
|
||||||
const cookieFit = 'webreader.fit'
|
const cookieFit = 'webreader.fit'
|
||||||
const cookieContinuousReaderFit = 'webreader.continuousReaderFit'
|
const cookieContinuousReaderFit = 'webreader.continuousReaderFit'
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,28 @@
|
||||||
|
|
||||||
<v-spacer/>
|
<v-spacer/>
|
||||||
|
|
||||||
|
<!-- Context notification for navigation -->
|
||||||
|
<v-alert
|
||||||
|
v-if="contextReadList"
|
||||||
|
type="info"
|
||||||
|
text
|
||||||
|
dense
|
||||||
|
border="right"
|
||||||
|
class="mb-0"
|
||||||
|
>
|
||||||
|
Navigation within the readlist: {{ contextName }}
|
||||||
|
</v-alert>
|
||||||
|
|
||||||
|
<!-- Navigate to previous book -->
|
||||||
<v-btn
|
<v-btn
|
||||||
icon
|
icon
|
||||||
:disabled="$_.isEmpty(siblingPrevious)"
|
:disabled="$_.isEmpty(siblingPrevious)"
|
||||||
:to="{ name: 'browse-book', params: { bookId: previousId } }"
|
:to="{ name: 'browse-book', params: { bookId: previousId }, query: { context: context.origin, contextId: context.id} }"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-chevron-left</v-icon>
|
<v-icon>mdi-chevron-left</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
|
<!-- List of all books in context (series/readlist) for navigation -->
|
||||||
<v-menu bottom
|
<v-menu bottom
|
||||||
offset-y
|
offset-y
|
||||||
:max-height="$vuetify.breakpoint.height * .7"
|
:max-height="$vuetify.breakpoint.height * .7"
|
||||||
|
|
@ -38,7 +52,7 @@
|
||||||
<v-list-item
|
<v-list-item
|
||||||
v-for="(book, i) in siblings"
|
v-for="(book, i) in siblings"
|
||||||
:key="i"
|
:key="i"
|
||||||
:to="{ name: 'browse-book', params: { bookId: book.id } }"
|
:to="{ name: 'browse-book', params: { bookId: book.id }, query: { context: context.origin, contextId: context.id} }"
|
||||||
>
|
>
|
||||||
<v-list-item-title class="text-wrap text-body-2">{{ book.metadata.number }} - {{ book.metadata.title }}
|
<v-list-item-title class="text-wrap text-body-2">{{ book.metadata.number }} - {{ book.metadata.title }}
|
||||||
</v-list-item-title>
|
</v-list-item-title>
|
||||||
|
|
@ -47,10 +61,11 @@
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-menu>
|
</v-menu>
|
||||||
|
|
||||||
|
<!-- Navigate to next book -->
|
||||||
<v-btn
|
<v-btn
|
||||||
icon
|
icon
|
||||||
:disabled="$_.isEmpty(siblingNext)"
|
:disabled="$_.isEmpty(siblingNext)"
|
||||||
:to="{ name: 'browse-book', params: { bookId: nextId } }"
|
:to="{ name: 'browse-book', params: { bookId: nextId }, query: { context: context.origin, contextId: context.id} }"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-chevron-right</v-icon>
|
<v-icon>mdi-chevron-right</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
@ -212,6 +227,8 @@ import { ReadStatus } from '@/types/enum-books'
|
||||||
import { BOOK_CHANGED, LIBRARY_DELETED } from '@/types/events'
|
import { BOOK_CHANGED, LIBRARY_DELETED } from '@/types/events'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import ReadListsExpansionPanels from '@/components/ReadListsExpansionPanels.vue'
|
import ReadListsExpansionPanels from '@/components/ReadListsExpansionPanels.vue'
|
||||||
|
import { BookDto, BookFormat } from '@/types/komga-books'
|
||||||
|
import { Context, ContextOrigin } from '@/types/context'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'BrowseBook',
|
name: 'BrowseBook',
|
||||||
|
|
@ -220,6 +237,8 @@ export default Vue.extend({
|
||||||
return {
|
return {
|
||||||
book: {} as BookDto,
|
book: {} as BookDto,
|
||||||
series: {} as SeriesDto,
|
series: {} as SeriesDto,
|
||||||
|
context: {} as Context,
|
||||||
|
contextName: '',
|
||||||
siblings: [] as BookDto[],
|
siblings: [] as BookDto[],
|
||||||
siblingPrevious: {} as BookDto,
|
siblingPrevious: {} as BookDto,
|
||||||
siblingNext: {} as BookDto,
|
siblingNext: {} as BookDto,
|
||||||
|
|
@ -288,6 +307,9 @@ export default Vue.extend({
|
||||||
nextId (): string {
|
nextId (): string {
|
||||||
return this.siblingNext?.id?.toString() || '0'
|
return this.siblingNext?.id?.toString() || '0'
|
||||||
},
|
},
|
||||||
|
contextReadList (): boolean {
|
||||||
|
return this.context.origin === ContextOrigin.READLIST
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
libraryDeleted (event: EventLibraryDeleted) {
|
libraryDeleted (event: EventLibraryDeleted) {
|
||||||
|
|
@ -301,7 +323,30 @@ export default Vue.extend({
|
||||||
async loadBook (bookId: string) {
|
async loadBook (bookId: string) {
|
||||||
this.book = await this.$komgaBooks.getBook(bookId)
|
this.book = await this.$komgaBooks.getBook(bookId)
|
||||||
this.series = await this.$komgaSeries.getOneSeries(this.book.seriesId)
|
this.series = await this.$komgaSeries.getOneSeries(this.book.seriesId)
|
||||||
|
|
||||||
|
// parse query params to get context and contextId
|
||||||
|
if (this.$route.query.contextId && this.$route.query.context
|
||||||
|
&& Object.values(ContextOrigin).includes(this.$route.query.context as ContextOrigin)) {
|
||||||
|
this.context = {
|
||||||
|
origin: this.$route.query.context as ContextOrigin,
|
||||||
|
id: this.$route.query.contextId as string,
|
||||||
|
}
|
||||||
|
this.book.context = this.context
|
||||||
|
this.contextName = (await (this.$komgaReadLists.getOneReadList(this.context.id))).name
|
||||||
|
} else {
|
||||||
|
this.context = {
|
||||||
|
origin: ContextOrigin.SERIES,
|
||||||
|
id: this.book.seriesId,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get siblings depending on origin
|
||||||
|
if (this?.context.origin === ContextOrigin.SERIES) {
|
||||||
this.siblings = (await this.$komgaSeries.getBooks(this.book.seriesId, { unpaged: true } as PageRequest)).content
|
this.siblings = (await this.$komgaSeries.getBooks(this.book.seriesId, { unpaged: true } as PageRequest)).content
|
||||||
|
} else if (this.context.origin === ContextOrigin.READLIST) {
|
||||||
|
this.siblings = (await this.$komgaReadLists.getBooks(this.context.id, { unpaged: true } as PageRequest)).content
|
||||||
|
}
|
||||||
|
|
||||||
this.readLists = await this.$komgaBooks.getReadLists(this.bookId)
|
this.readLists = await this.$komgaBooks.getReadLists(this.bookId)
|
||||||
|
|
||||||
if (this.$_.has(this.book, 'metadata.title')) {
|
if (this.$_.has(this.book, 'metadata.title')) {
|
||||||
|
|
@ -309,12 +354,20 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (this?.context.origin === ContextOrigin.SERIES) {
|
||||||
this.siblingNext = await this.$komgaBooks.getBookSiblingNext(bookId)
|
this.siblingNext = await this.$komgaBooks.getBookSiblingNext(bookId)
|
||||||
|
} else if (this.context.origin === ContextOrigin.READLIST) {
|
||||||
|
this.siblingNext = await this.$komgaReadLists.getBookSiblingNext(this.context.id, bookId)
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.siblingNext = {} as BookDto
|
this.siblingNext = {} as BookDto
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
if (this?.context.origin === ContextOrigin.SERIES) {
|
||||||
this.siblingPrevious = await this.$komgaBooks.getBookSiblingPrevious(bookId)
|
this.siblingPrevious = await this.$komgaBooks.getBookSiblingPrevious(bookId)
|
||||||
|
} else if (this.context.origin === ContextOrigin.READLIST) {
|
||||||
|
this.siblingPrevious = await this.$komgaReadLists.getBookSiblingPrevious(this.context.id, bookId)
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.siblingPrevious = {} as BookDto
|
this.siblingPrevious = {} as BookDto
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,8 @@ import { BOOK_CHANGED, READLIST_CHANGED, READLIST_DELETED } from '@/types/events
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import ReadListActionsMenu from '@/components/menus/ReadListActionsMenu.vue'
|
import ReadListActionsMenu from '@/components/menus/ReadListActionsMenu.vue'
|
||||||
import BooksMultiSelectBar from '@/components/bars/BooksMultiSelectBar.vue'
|
import BooksMultiSelectBar from '@/components/bars/BooksMultiSelectBar.vue'
|
||||||
|
import { BookDto, ReadProgressUpdateDto } from '@/types/komga-books'
|
||||||
|
import { ContextOrigin } from '@/types/context'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'BrowseReadList',
|
name: 'BrowseReadList',
|
||||||
|
|
@ -156,6 +158,7 @@ export default Vue.extend({
|
||||||
async loadReadList (readListId: string) {
|
async loadReadList (readListId: string) {
|
||||||
this.readList = await this.$komgaReadLists.getOneReadList(readListId)
|
this.readList = await this.$komgaReadLists.getOneReadList(readListId)
|
||||||
this.books = (await this.$komgaReadLists.getBooks(readListId, { unpaged: true } as PageRequest)).content
|
this.books = (await this.$komgaReadLists.getBooks(readListId, { unpaged: true } as PageRequest)).content
|
||||||
|
this.books.forEach((x: BookDto) => x.context = { origin: ContextOrigin.READLIST, id: readListId })
|
||||||
this.booksCopy = [...this.books]
|
this.booksCopy = [...this.books]
|
||||||
this.selectedBooks = []
|
this.selectedBooks = []
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,7 @@ import { ReadStatus } from '@/types/enum-books'
|
||||||
import { BOOK_CHANGED, LIBRARY_DELETED, READLIST_CHANGED, SERIES_CHANGED } from '@/types/events'
|
import { BOOK_CHANGED, LIBRARY_DELETED, READLIST_CHANGED, SERIES_CHANGED } from '@/types/events'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { Location } from 'vue-router'
|
import { Location } from 'vue-router'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
import { SeriesStatus } from '@/types/enum-series'
|
import { SeriesStatus } from '@/types/enum-series'
|
||||||
import FilterDrawer from '@/components/FilterDrawer.vue'
|
import FilterDrawer from '@/components/FilterDrawer.vue'
|
||||||
import FilterList from '@/components/FilterList.vue'
|
import FilterList from '@/components/FilterList.vue'
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ import EmptyState from '@/components/EmptyState.vue'
|
||||||
import HorizontalScroller from '@/components/HorizontalScroller.vue'
|
import HorizontalScroller from '@/components/HorizontalScroller.vue'
|
||||||
import ItemBrowser from '@/components/ItemBrowser.vue'
|
import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||||
import { ReadStatus } from '@/types/enum-books'
|
import { ReadStatus } from '@/types/enum-books'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
import { BOOK_CHANGED, LIBRARY_DELETED, SERIES_CHANGED } from '@/types/events'
|
import { BOOK_CHANGED, LIBRARY_DELETED, SERIES_CHANGED } from '@/types/events'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
|
||||||
import EmptyState from '@/components/EmptyState.vue'
|
import EmptyState from '@/components/EmptyState.vue'
|
||||||
import HorizontalScroller from '@/components/HorizontalScroller.vue'
|
import HorizontalScroller from '@/components/HorizontalScroller.vue'
|
||||||
import ItemBrowser from '@/components/ItemBrowser.vue'
|
import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
import {
|
import {
|
||||||
BOOK_CHANGED,
|
BOOK_CHANGED,
|
||||||
COLLECTION_CHANGED,
|
COLLECTION_CHANGED,
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { MediaStatus } from '@/types/enum-books'
|
import { MediaStatus } from '@/types/enum-books'
|
||||||
|
import { BookDto } from '@/types/komga-books'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'SettingsMediaAnalysis',
|
name: 'SettingsMediaAnalysis',
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue