feat(webui): display book aggregated data on series screen

closes #181
This commit is contained in:
Gauthier Roebroeck 2021-01-11 17:13:16 +08:00
parent eb029d9bb5
commit e642174c84
19 changed files with 78 additions and 4 deletions

View File

@ -93,6 +93,7 @@ import ReadListAddToDialog from '@/components/dialogs/ReadListAddToDialog.vue'
import ReadListDeleteDialog from '@/components/dialogs/ReadListDeleteDialog.vue'
import ReadListEditDialog from '@/components/dialogs/ReadListEditDialog.vue'
import { BookDto } from '@/types/komga-books'
import {SeriesDto} from "@/types/komga-series";
export default Vue.extend({
name: 'Dialogs',

View File

@ -125,6 +125,7 @@ import Vue from 'vue'
import { RawLocation } from 'vue-router'
import ReadListActionsMenu from '@/components/menus/ReadListActionsMenu.vue'
import { BookDto } from '@/types/komga-books'
import {SeriesDto} from "@/types/komga-series";
export default Vue.extend({
name: 'ItemCard',

View File

@ -106,6 +106,7 @@ import { bookThumbnailUrl, collectionThumbnailUrl, readListThumbnailUrl, seriesT
import { debounce } from 'lodash'
import Vue from 'vue'
import { BookDto } from '@/types/komga-books'
import {SeriesDto} from "@/types/komga-series";
export default Vue.extend({
name: 'SearchBox',

View File

@ -88,6 +88,7 @@
<script lang="ts">
import Vue from 'vue'
import {SeriesDto} from "@/types/komga-series";
export default Vue.extend({
name: 'CollectionAddToDialog',

View File

@ -319,6 +319,7 @@ import Vue from 'vue'
import { SeriesStatus } from '@/types/enum-series'
import { helpers, minValue, requiredIf } from 'vuelidate/lib/validators'
import { ReadingDirection } from '@/types/enum-books'
import {SeriesDto} from "@/types/komga-series";
const tags = require('language-tags')

View File

@ -29,6 +29,7 @@
<script lang="ts">
import { SERIES_CHANGED, seriesToEventSeriesChanged } from '@/types/events'
import Vue from 'vue'
import {SeriesDto} from "@/types/komga-series";
export default Vue.extend({
name: 'SeriesActionsMenu',

View File

@ -1,4 +1,5 @@
import { AxiosInstance } from 'axios'
import {SeriesDto} from "@/types/komga-series";
const qs = require('qs')

View File

@ -1,5 +1,6 @@
import { AxiosInstance } from 'axios'
import { BookDto } from '@/types/komga-books'
import {SeriesDto, SeriesMetadataUpdateDto} from "@/types/komga-series";
const qs = require('qs')

View File

@ -1,6 +1,7 @@
import Vue from 'vue'
import Vuex from 'vuex'
import { BookDto } from '@/types/komga-books'
import {SeriesDto} from "@/types/komga-series";
Vue.use(Vuex)

View File

@ -1,4 +1,5 @@
import { BookDto } from '@/types/komga-books'
import {SeriesDto} from "@/types/komga-series";
export const BOOK_CHANGED = 'book-changed'
export const SERIES_CHANGED = 'series-changed'

View File

@ -1,6 +1,7 @@
import { bookThumbnailUrl, collectionThumbnailUrl, readListThumbnailUrl, seriesThumbnailUrl } from '@/functions/urls'
import { RawLocation } from 'vue-router/types/router'
import { BookDto } from '@/types/komga-books'
import {SeriesDto} from "@/types/komga-series";
function plural (count: number, singular: string, plural: string) {
return `${count} ${count === 1 ? singular : plural}`

View File

@ -1,4 +1,6 @@
interface SeriesDto {
import {AuthorDto} from "@/types/komga-books";
export interface SeriesDto {
id: string,
libraryId: string,
name: string,
@ -8,10 +10,11 @@ interface SeriesDto {
booksReadCount: number,
booksUnreadCount: number,
booksInProgressCount: number,
metadata: SeriesMetadata
metadata: SeriesMetadataDto,
booksMetadata: SeriesBooksMetadataDto,
}
interface SeriesMetadata {
export interface SeriesMetadataDto {
status: string,
statusLock: boolean,
created: string,
@ -36,7 +39,16 @@ interface SeriesMetadata {
tagsLock: boolean
}
interface SeriesMetadataUpdateDto {
export interface SeriesBooksMetadataDto {
created: string,
lastModified: string
authors: AuthorDto[],
releaseDate: string,
summary: string,
summaryNumber: string,
}
export interface SeriesMetadataUpdateDto {
status?: string,
statusLock?: boolean,
title?: string,

View File

@ -290,6 +290,7 @@ import { shortcutsAll } from '@/functions/shortcuts/reader'
import { shortcutsSettingsContinuous } from '@/functions/shortcuts/continuous-reader'
import { BookDto, PageDto, PageDtoWithUrl } from '@/types/komga-books'
import { Context, ContextOrigin } from '@/types/context'
import {SeriesDto} from "@/types/komga-series";
const cookieFit = 'webreader.fit'
const cookieContinuousReaderFit = 'webreader.continuousReaderFit'

View File

@ -229,6 +229,7 @@ import Vue from 'vue'
import ReadListsExpansionPanels from '@/components/ReadListsExpansionPanels.vue'
import { BookDto, BookFormat } from '@/types/komga-books'
import { Context, ContextOrigin } from '@/types/context'
import {SeriesDto} from "@/types/komga-series";
export default Vue.extend({
name: 'BrowseBook',

View File

@ -122,6 +122,7 @@ import FilterList from '@/components/FilterList.vue'
import { Location } from 'vue-router'
import EmptyState from '@/components/EmptyState.vue'
import { parseQueryFilter } from '@/functions/query-params'
import {SeriesDto} from "@/types/komga-series";
export default Vue.extend({
name: 'BrowseCollection',

View File

@ -105,6 +105,7 @@ import SortList from '@/components/SortList.vue'
import FilterPanels from '@/components/FilterPanels.vue'
import FilterList from '@/components/FilterList.vue'
import { mergeFilterParams, sortOrFilterActive, toNameValue } from '@/functions/filter'
import {SeriesDto} from "@/types/komga-series";
const cookiePageSize = 'pagesize'

View File

@ -111,6 +111,34 @@
</v-col>
</v-row>
<v-row class="mt-3" v-if="!series.metadata.summary && series.booksMetadata.summary">
<v-col>
<v-tooltip right>
<template v-slot:activator="{ on }">
<span v-on="on" class="text-caption">Summary from book {{ series.booksMetadata.summaryNumber }}:</span>
</template>
This series has no summary, so we picked one for you!
</v-tooltip>
<div class="text-body-1"
style="white-space: pre-wrap"
>
{{ series.booksMetadata.summary }}
</div>
</v-col>
</v-row>
<v-row v-if="series.booksMetadata.releaseDate">
<v-col cols="6" sm="4" md="2" class="text-body-2 py-1">YEAR</v-col>
<v-col class="text-body-2 text-capitalize py-1">
<v-tooltip right>
<template v-slot:activator="{ on }">
<span v-on="on">{{ series.booksMetadata.releaseDate | moment('YYYY') }}</span>
</template>
This is the earliest year from the release dates from all books in the series
</v-tooltip>
</v-col>
</v-row>
<v-row v-if="series.metadata.publisher">
<v-col cols="6" sm="4" md="2" class="text-body-2 py-1">PUBLISHER</v-col>
<v-col class="text-body-2 text-capitalize py-1">
@ -146,6 +174,18 @@
</v-col>
</v-row>
<v-row class="text-body-2"
v-for="(names, key) in authorsByRole"
:key="key"
>
<v-col cols="6" sm="4" md="2" class="py-1 text-uppercase">{{ key }}</v-col>
<v-col class="py-1">
<span v-for="(name, i) in names"
:key="name"
>{{ i === 0 ? '' : ', ' }}{{ name }}</span>
</v-col>
</v-row>
<v-row v-if="$vuetify.breakpoint.name !== 'xs'">
<v-col>
<collections-expansion-panels :collections="collections"/>
@ -212,6 +252,8 @@ import FilterList from '@/components/FilterList.vue'
import SortList from '@/components/SortList.vue'
import { mergeFilterParams, sortOrFilterActive, toNameValue } from '@/functions/filter'
import FilterPanels from '@/components/FilterPanels.vue'
import {SeriesDto} from "@/types/komga-series";
import {groupAuthorsByRolePlural} from "@/functions/authors";
const tags = require('language-tags')
@ -305,6 +347,9 @@ export default Vue.extend({
sortOrFilterActive (): boolean {
return sortOrFilterActive(this.sortActive, this.sortDefault, this.filters)
},
authorsByRole (): any {
return groupAuthorsByRolePlural(this.series.booksMetadata.authors)
},
},
props: {
seriesId: {

View File

@ -114,6 +114,7 @@ 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";
export default Vue.extend({
name: 'Dashboard',

View File

@ -118,6 +118,7 @@ import {
SERIES_CHANGED,
} from '@/types/events'
import Vue from 'vue'
import {SeriesDto} from "@/types/komga-series";
export default Vue.extend({
name: 'Search',