fix(webui): rearrange browse series and books views

This commit is contained in:
Gauthier Roebroeck 2021-03-03 14:08:37 +08:00
parent 7cc837cc41
commit a5c7b17829
4 changed files with 366 additions and 311 deletions

View file

@ -22,9 +22,6 @@
<v-list-item @click="markUnread" v-if="!isUnread">
<v-list-item-title>{{ $t('menu.mark_unread') }}</v-list-item-title>
</v-list-item>
<v-list-item v-if="canDownload" :href="fileUrl">
<v-list-item-title>{{ $t('menu.download_series') }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</div>
@ -33,7 +30,6 @@
import {SERIES_CHANGED, seriesToEventSeriesChanged} from '@/types/events'
import Vue from 'vue'
import {SeriesDto} from "@/types/komga-series";
import {seriesFileUrl} from "@/functions/urls";
export default Vue.extend({
name: 'SeriesActionsMenu',
@ -61,12 +57,6 @@ export default Vue.extend({
isAdmin (): boolean {
return this.$store.getters.meAdmin
},
canDownload (): boolean {
return this.$store.getters.meFileDownload
},
fileUrl (): string {
return seriesFileUrl(this.series.id)
},
isRead (): boolean {
return this.series.booksReadCount === this.series.booksCount
},

View file

@ -139,7 +139,9 @@
"series": "Series",
"tags": "Tags",
"use_filter_panel_to_change_filter": "Use the filter panel to change the active filter",
"year": "year"
"year": "year",
"download": "Download",
"read": "Read"
},
"dashboard": {
"keep_reading": "Keep Reading",

View file

@ -99,155 +99,174 @@
</v-col>
</v-row>
<v-row class="text-body-2">
<v-col>
<span class="mx-3">{{ book.metadata.number }}</span>
<v-row class="text-caption">
<v-col cols="auto">
{{ book.metadata.number }} · {{ book.media.pagesCount }} {{ $t('common.pages') }}
</v-col>
<v-col cols="auto" v-if="book.metadata.releaseDate">
{{ book.metadata.releaseDate | moment('MMMM DD, YYYY') }}
</v-col>
</v-row>
<v-divider v-if="book.metadata.summary"/>
<v-row class="mt-3" v-if="book.metadata.summary">
<v-col>
<read-more>{{ book.metadata.summary }}</read-more>
</v-col>
</v-row>
<div class="hidden-xs-only">
<v-row class="align-center">
<v-col cols="auto">
<v-btn color="accent"
small
:title="$t('browse_book.read_book')"
:to="{name: 'read-book', params: { bookId: bookId}, query: { context: context.origin, contextId: context.id}}"
:disabled="book.media.status !== 'READY' || !canReadPages"
>
<v-icon left>mdi-book-open-page-variant</v-icon>
{{ $t('common.read') }}
</v-btn>
</v-col>
<v-col cols="auto">
<v-btn :title="$t('browse_book.download_file')"
small
:disabled="!canDownload"
:href="fileUrl">
<v-icon left>mdi-file-download</v-icon>
{{ $t('common.download') }}
</v-btn>
</v-col>
</v-row>
<v-divider v-if="book.metadata.authors.length > 0"/>
<div v-for="role in authorRoles"
:key="role"
>
<v-row class="align-center text-body-2"
v-if="authorsByRole[role]"
>
<v-col cols="6" sm="4" md="3" class="py-1 text-uppercase">{{ $t(`author_roles.${role}`) }}</v-col>
<v-col cols="6" sm="8" md="9" class="py-1">
<vue-horizontal>
<template v-slot:btn-prev>
<v-btn icon small>
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
</template>
<template v-slot:btn-next>
<v-btn icon small>
<v-icon>mdi-chevron-right</v-icon>
</v-btn>
</template>
<v-chip v-for="(name, i) in authorsByRole[role]"
:key="i"
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
:title="name"
:to="{name:'browse-series', params: {seriesId: book.seriesId }, query: {[role]: name}}"
label
small
outlined
link
>{{ name }}
</v-chip>
</vue-horizontal>
<v-row v-if="book.metadata.summary">
<v-col>
<read-more>{{ book.metadata.summary }}</read-more>
</v-col>
</v-row>
</div>
<v-row v-if="book.metadata.tags.length > 0" class="align-center text-body-2">
<v-col cols="6" sm="4" md="3" class="py-1">TAGS</v-col>
<v-col cols="6" sm="8" md="9" class="py-1 text-capitalize">
<vue-horizontal>
<template v-slot:btn-prev>
<v-btn icon small>
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
</template>
<template v-slot:btn-next>
<v-btn icon small>
<v-icon>mdi-chevron-right</v-icon>
</v-btn>
</template>
<v-chip v-for="(t, i) in book.metadata.tags"
:key="i"
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
:title="t"
:to="{name:'browse-series', params: {seriesId: book.seriesId}, query: {tag: t}}"
label
small
outlined
link
>{{ t }}
</v-chip>
</vue-horizontal>
</v-col>
</v-row>
<v-row v-if="$vuetify.breakpoint.name !== 'xs'">
<v-col>
<read-lists-expansion-panels :read-lists="readLists"/>
</v-col>
</v-row>
</v-col>
</v-row>
<v-row v-if="$vuetify.breakpoint.name === 'xs'">
<v-col class="pt-0 py-1">
<div class="hidden-sm-and-up">
<v-row class="align-center">
<v-col cols="auto">
<v-btn color="accent"
small
:title="$t('browse_book.read_book')"
:to="{name: 'read-book', params: { bookId: bookId}, query: { context: context.origin, contextId: context.id}}"
:disabled="book.media.status !== 'READY' || !canReadPages"
>
<v-icon left>mdi-book-open-page-variant</v-icon>
{{ $t('common.read') }}
</v-btn>
</v-col>
<v-col cols="auto">
<v-btn :title="$t('browse_book.download_file')"
small
:disabled="!canDownload"
:href="fileUrl">
<v-icon left>mdi-file-download</v-icon>
{{ $t('common.download') }}
</v-btn>
</v-col>
</v-row>
<v-row v-if="book.metadata.summary">
<v-col>
<read-more>{{ book.metadata.summary }}</read-more>
</v-col>
</v-row>
</div>
<div v-for="role in authorRoles"
:key="role"
>
<v-row class="align-center text-caption"
v-if="authorsByRole[role]"
>
<v-col cols="4" sm="3" md="2" xl="1" class="py-1 text-uppercase">{{ $t(`author_roles.${role}`) }}</v-col>
<v-col cols="8" sm="9" md="10" xl="11" class="py-1">
<vue-horizontal>
<template v-slot:btn-prev>
<v-btn icon small>
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
</template>
<template v-slot:btn-next>
<v-btn icon small>
<v-icon>mdi-chevron-right</v-icon>
</v-btn>
</template>
<v-chip v-for="(name, i) in authorsByRole[role]"
:key="i"
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
:title="name"
:to="{name:'browse-series', params: {seriesId: book.seriesId }, query: {[role]: name}}"
label
small
outlined
link
>{{ name }}
</v-chip>
</vue-horizontal>
</v-col>
</v-row>
</div>
<v-row v-if="book.metadata.tags.length > 0" class="align-center text-caption">
<v-col cols="4" sm="3" md="2" xl="1" class="py-1">TAGS</v-col>
<v-col cols="8" sm="9" md="10" xl="11" class="py-1 text-capitalize">
<vue-horizontal>
<template v-slot:btn-prev>
<v-btn icon small>
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
</template>
<template v-slot:btn-next>
<v-btn icon small>
<v-icon>mdi-chevron-right</v-icon>
</v-btn>
</template>
<v-chip v-for="(t, i) in book.metadata.tags"
:key="i"
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
:title="t"
:to="{name:'browse-series', params: {seriesId: book.seriesId}, query: {tag: t}}"
label
small
outlined
link
>{{ t }}
</v-chip>
</vue-horizontal>
</v-col>
</v-row>
<v-row>
<v-col>
<read-lists-expansion-panels :read-lists="readLists"/>
</v-col>
</v-row>
<v-row align="center">
<v-col cols="auto">
<v-btn icon
:title="$t('browse_book.download_file')"
class="pb-1"
:disabled="!canDownload"
:href="fileUrl">
<v-icon>mdi-file-download</v-icon>
</v-btn>
</v-col>
<v-col cols="auto">
<v-btn icon
color="accent"
:title="$t('browse_book.read_book')"
class="pb-1"
:to="{name: 'read-book', params: { bookId: bookId}, query: { context: context.origin, contextId: context.id}}"
:disabled="book.media.status !== 'READY' || !canReadPages"
>
<v-icon>mdi-book-open-page-variant</v-icon>
</v-btn>
</v-col>
<v-col cols="auto">
<v-icon class="mx-2 pb-1">mdi-book-open</v-icon>
<span class="text-body-2">{{ book.media.pagesCount }} {{ $t('common.pages') }}</span>
</v-col>
<v-row class="align-center text-caption">
<v-col class="py-1" cols="4" sm="3" md="2" xl="1">{{ $t('browse_book.size') }}</v-col>
<v-col class="py-1" cols="8" sm="9" md="10" xl="11">{{ book.size }}</v-col>
</v-row>
<v-row>
<v-col cols="3" md="2" lg="2" xl="1" class="text-body-2">{{ $t('browse_book.size') }}</v-col>
<v-col cols="9" class="text-body-2">{{ book.size }}</v-col>
</v-row>
<v-row v-if="book.media.comment">
<v-col cols="3" md="2" lg="2" xl="1" class="text-body-2">{{ $t('browse_book.comment') }}</v-col>
<v-col cols="9" class="text-body-2">
<v-row v-if="book.media.comment" class="align-center text-caption">
<v-col class="py-1" cols="4" sm="3" md="2" xl="1">{{ $t('browse_book.comment') }}</v-col>
<v-col class="py-1" cols="8" sm="9" md="10" xl="11">
<span class="error--text font-weight-bold">{{ book.media.comment }}</span>
</v-col>
</v-row>
<v-row>
<v-col cols="3" md="2" lg="2" xl="1" class="text-body-2">{{ $t('browse_book.format') }}</v-col>
<v-col cols="9" class="text-body-2">
<span>{{ format.type }}</span>
<v-row class="align-center text-caption">
<v-col class="py-1" cols="4" sm="3" md="2" xl="1">{{ $t('browse_book.format') }}</v-col>
<v-col class="py-1" cols="8" sm="9" md="10" xl="11">
{{ format.type }}
</v-col>
</v-row>
<v-row align="center">
<v-col cols="3" md="2" lg="2" xl="1" class="text-body-2">{{ $t('browse_book.file') }}</v-col>
<v-col cols="9" class="text-body-2">{{ book.url }}</v-col>
<v-row class="align-center text-caption">
<v-col class="py-1" cols="4" sm="3" md="2" xl="1">{{ $t('browse_book.file') }}</v-col>
<v-col class="py-1" cols="8" sm="9" md="10" xl="11">{{ book.url }}</v-col>
</v-row>
</v-container>
@ -332,7 +351,7 @@ export default Vue.extend({
format(): BookFormat {
return getBookFormatFromMediaType(this.book.media.mediaType)
},
authorsByRole (): any {
authorsByRole(): any {
return groupAuthorsByRole(this.book.metadata.authors)
},
isRead(): boolean {

View file

@ -1,5 +1,5 @@
<template>
<div>
<div v-if="!$_.isEmpty(series)">
<toolbar-sticky v-if="selectedBooks.length === 0">
<!-- Go back to parent library -->
<v-btn icon
@ -67,7 +67,7 @@
</template>
</filter-drawer>
<v-container fluid>
<v-container fluid class="px-6">
<v-row>
<v-col cols="4" sm="4" md="auto" lg="auto" xl="auto">
<item-card
@ -78,76 +78,17 @@
no-link
:action-menu="false"
></item-card>
</v-col>
<v-col cols="8" v-if="series.metadata">
<v-col cols="8">
<v-row>
<v-col>
<v-col class="py-1">
<div class="text-h5" v-if="$_.get(series, 'metadata.title')">{{ series.metadata.title }}</div>
</v-col>
</v-row>
<v-row class="text-body-2">
<v-col>
<v-chip
label
small
link
:color="statusChip.color"
:text-color="statusChip.text"
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {status: series.metadata.status}}"
>
{{ $t(`enums.series_status.${series.metadata.status}`) }}
</v-chip>
<v-chip
label
small
link
v-if="series.metadata.ageRating"
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {ageRating: series.metadata.ageRating}}"
class="mx-1"
>
{{ series.metadata.ageRating }}+
</v-chip>
<v-chip
label
small
link
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {language: series.metadata.language}}"
v-if="series.metadata.language"
class="mx-1"
>
{{ languageDisplay }}
</v-chip>
<v-chip label small v-if="series.metadata.readingDirection" class="mx-1">
{{ $t(`enums.reading_direction.${series.metadata.readingDirection}`) }}
</v-chip>
</v-col>
</v-row>
<v-row class="mt-3" v-if="series.metadata.summary">
<v-col>
<read-more> {{ series.metadata.summary }}</read-more>
</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">
{{ $t('browse_series.summary_from_book', {number: series.booksMetadata.summaryNumber}) }}
</span>
</template>
{{ $t('browse_series.series_no_summary') }}
</v-tooltip>
<read-more>{{ series.booksMetadata.summary }}</read-more>
</v-col>
</v-row>
<v-row v-if="series.booksMetadata.releaseDate">
<v-col cols="6" sm="4" md="3" class="text-body-2 py-1 text-uppercase">{{ $t('common.year') }}</v-col>
<v-col class="text-body-2 text-capitalize py-1">
<v-row v-if="series.booksMetadata.releaseDate" class="align-center text-caption">
<v-col class="py-1">
<v-tooltip right>
<template v-slot:activator="{ on }">
<span v-on="on">{{ series.booksMetadata.releaseDate | moment('YYYY') }}</span>
@ -157,130 +98,227 @@
</v-col>
</v-row>
<v-row v-if="series.metadata.publisher" class="align-center text-body-2">
<v-col cols="6" sm="4" md="3" class="py-1 text-uppercase">{{ $t('common.publisher') }}</v-col>
<v-col class="py-1">
<v-chip
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
:title="series.metadata.publisher"
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {publisher: series.metadata.publisher}}"
label
small
outlined
link
>{{ series.metadata.publisher }}
<v-row class="text-body-2">
<v-col :class="'py-1 ' + ($vuetify.rtl ? 'pl-0' : 'pr-0')" cols="auto">
<v-chip label small link :color="statusChip.color" :text-color="statusChip.text"
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {status: series.metadata.status}}">
{{ $t(`enums.series_status.${series.metadata.status}`) }}
</v-chip>
</v-col>
<v-col :class="'py-1 ' + ($vuetify.rtl ? 'pl-0' : 'pr-0')" cols="auto">
<v-chip label small link v-if="series.metadata.ageRating"
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {ageRating: series.metadata.ageRating}}"
>
{{ series.metadata.ageRating }}+
</v-chip>
</v-col>
<v-col :class="'py-1 ' + ($vuetify.rtl ? 'pl-0' : 'pr-0')" cols="auto">
<v-chip label small link
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {language: series.metadata.language}}"
v-if="series.metadata.language"
>
{{ languageDisplay }}
</v-chip>
</v-col>
<v-col :class="'py-1 ' + ($vuetify.rtl ? 'pl-0' : 'pr-0')" cols="auto">
<v-chip label small v-if="series.metadata.readingDirection">
{{ $t(`enums.reading_direction.${series.metadata.readingDirection}`) }}
</v-chip>
</v-col>
</v-row>
<v-row v-if="series.metadata.genres.length > 0" class="align-center text-body-2">
<v-col cols="6" sm="4" md="3" class="py-1 text-uppercase">{{ $t('common.genre') }}</v-col>
<v-col cols="6" sm="8" md="9" class="py-1 text-capitalize">
<vue-horizontal>
<template v-slot:btn-prev>
<v-btn icon small>
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
</template>
<div class="hidden-xs-only">
<v-row class="align-center">
<v-col cols="auto">
<v-btn :title="$t('menu.download_series')"
small
:disabled="!canDownload"
:href="fileUrl">
<v-icon left>mdi-file-download</v-icon>
{{ $t('common.download') }}
</v-btn>
</v-col>
</v-row>
<template v-slot:btn-next>
<v-btn icon small>
<v-icon>mdi-chevron-right</v-icon>
</v-btn>
</template>
<v-chip v-for="(t, i) in series.metadata.genres"
:key="i"
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
:title="t"
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {genre: t}}"
label
small
outlined
link
>{{ t }}
</v-chip>
</vue-horizontal>
</v-col>
</v-row>
<v-row v-if="series.metadata.summary">
<v-col>
<read-more>{{ series.metadata.summary }}</read-more>
</v-col>
</v-row>
<v-row v-if="series.metadata.tags.length > 0" class="align-center text-body-2">
<v-col cols="6" sm="4" md="3" class="py-1 text-uppercase">{{ $t('common.tags') }}</v-col>
<v-col cols="6" sm="8" md="9" class="py-1 text-capitalize">
<vue-horizontal>
<template v-slot:btn-prev>
<v-btn icon small>
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
</template>
<template v-slot:btn-next>
<v-btn icon small>
<v-icon>mdi-chevron-right</v-icon>
</v-btn>
</template>
<v-chip v-for="(t, i) in series.metadata.tags"
:key="i"
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
:title="t"
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {tag: t}}"
label
small
outlined
link
>{{ t }}
</v-chip>
</vue-horizontal>
</v-col>
</v-row>
<v-divider v-if="series.booksMetadata.authors.length > 0"/>
<div v-for="role in authorRoles"
:key="role">
<v-row class="align-center text-body-2"
v-if="authorsByRole[role]"
>
<v-col cols="6" sm="4" md="3" class="py-1 text-uppercase">{{ $t(`author_roles.${role}`) }}</v-col>
<v-col cols="6" sm="8" md="9" class="py-1">
<vue-horizontal>
<template v-slot:btn-prev>
<v-btn icon small>
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
<v-row 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">
{{ $t('browse_series.summary_from_book', {number: series.booksMetadata.summaryNumber}) }}
</span>
</template>
<template v-slot:btn-next>
<v-btn icon small>
<v-icon>mdi-chevron-right</v-icon>
</v-btn>
</template>
<v-chip v-for="(name, i) in authorsByRole[role]"
:key="i"
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
:title="name"
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {[role]: name}}"
label
small
outlined
link
>{{ name }}
</v-chip>
</vue-horizontal>
{{ $t('browse_series.series_no_summary') }}
</v-tooltip>
<read-more>{{ series.booksMetadata.summary }}</read-more>
</v-col>
</v-row>
</div>
<v-row v-if="$vuetify.breakpoint.name !== 'xs'">
<v-col>
<collections-expansion-panels :collections="collections"/>
</v-col>
</v-row>
</v-col>
</v-row>
<v-row v-if="$vuetify.breakpoint.name === 'xs'">
<v-col class="pt-0 py-1">
<div class="hidden-sm-and-up">
<!-- Download button -->
<v-row class="align-center">
<v-col cols="auto">
<v-btn :title="$t('menu.download_series')"
small
:disabled="!canDownload"
:href="fileUrl">
<v-icon left>mdi-file-download</v-icon>
{{ $t('common.download') }}
</v-btn>
</v-col>
</v-row>
<!-- Series summary -->
<v-row v-if="series.metadata.summary">
<v-col>
<read-more>{{ series.metadata.summary }}</read-more>
</v-col>
</v-row>
<!-- Series summary from books -->
<v-row 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">
{{ $t('browse_series.summary_from_book', {number: series.booksMetadata.summaryNumber}) }}
</span>
</template>
{{ $t('browse_series.series_no_summary') }}
</v-tooltip>
<read-more>{{ series.booksMetadata.summary }}</read-more>
</v-col>
</v-row>
</div>
<!-- Pubisher -->
<v-row v-if="series.metadata.publisher" class="align-center text-caption">
<v-col cols="4" sm="3" md="2" xl="1" class="py-1 text-uppercase">{{ $t('common.publisher') }}</v-col>
<v-col cols="8" sm="9" md="10" xl="11" class="py-1">
<v-chip
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
:title="series.metadata.publisher"
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {publisher: series.metadata.publisher}}"
label
small
outlined
link
>{{ series.metadata.publisher }}
</v-chip>
</v-col>
</v-row>
<!-- Genres -->
<v-row v-if="series.metadata.genres.length > 0" class="align-center text-caption">
<v-col cols="4" sm="3" md="2" xl="1" class="py-1 text-uppercase">{{ $t('common.genre') }}</v-col>
<v-col cols="8" sm="9" md="10" xl="11" class="py-1 text-capitalize">
<vue-horizontal>
<template v-slot:btn-prev>
<v-btn icon small>
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
</template>
<template v-slot:btn-next>
<v-btn icon small>
<v-icon>mdi-chevron-right</v-icon>
</v-btn>
</template>
<v-chip v-for="(t, i) in series.metadata.genres"
:key="i"
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
:title="t"
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {genre: t}}"
label
small
outlined
link
>{{ t }}
</v-chip>
</vue-horizontal>
</v-col>
</v-row>
<!-- Tags -->
<v-row v-if="series.metadata.tags.length > 0" class="align-center text-caption">
<v-col cols="4" sm="3" md="2" xl="1" class="py-1 text-uppercase">{{ $t('common.tags') }}</v-col>
<v-col cols="8" sm="9" md="10" xl="11" class="py-1 text-capitalize">
<vue-horizontal>
<template v-slot:btn-prev>
<v-btn icon small>
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
</template>
<template v-slot:btn-next>
<v-btn icon small>
<v-icon>mdi-chevron-right</v-icon>
</v-btn>
</template>
<v-chip v-for="(t, i) in series.metadata.tags"
:key="i"
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
:title="t"
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {tag: t}}"
label
small
outlined
link
>{{ t }}
</v-chip>
</vue-horizontal>
</v-col>
</v-row>
<v-divider v-if="series.booksMetadata.authors.length > 0"/>
<div v-for="role in authorRoles"
:key="role">
<v-row class="align-center text-caption"
v-if="authorsByRole[role]"
>
<v-col cols="4" sm="3" md="2" xl="1" class="py-1 text-uppercase">{{ $t(`author_roles.${role}`) }}</v-col>
<v-col cols="8" sm="9" md="10" xl="11" class="py-1">
<vue-horizontal>
<template v-slot:btn-prev>
<v-btn icon small>
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
</template>
<template v-slot:btn-next>
<v-btn icon small>
<v-icon>mdi-chevron-right</v-icon>
</v-btn>
</template>
<v-chip v-for="(name, i) in authorsByRole[role]"
:key="i"
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
:title="name"
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {[role]: name}}"
label
small
outlined
link
>{{ name }}
</v-chip>
</vue-horizontal>
</v-col>
</v-row>
</div>
<v-row>
<v-col>
<collections-expansion-panels :collections="collections"/>
</v-col>
</v-row>
@ -332,7 +370,7 @@ import ItemCard from '@/components/ItemCard.vue'
import SeriesActionsMenu from '@/components/menus/SeriesActionsMenu.vue'
import PageSizeSelect from '@/components/PageSizeSelect.vue'
import {parseQueryFilter, parseQuerySort} from '@/functions/query-params'
import {seriesThumbnailUrl} from '@/functions/urls'
import {seriesFileUrl, seriesThumbnailUrl} from '@/functions/urls'
import {ReadStatus} from '@/types/enum-books'
import {BOOK_CHANGED, LIBRARY_DELETED, READLIST_CHANGED, SERIES_CHANGED} from '@/types/events'
import Vue from 'vue'
@ -424,6 +462,12 @@ export default Vue.extend({
isAdmin(): boolean {
return this.$store.getters.meAdmin
},
canDownload(): boolean {
return this.$store.getters.meFileDownload
},
fileUrl(): string {
return seriesFileUrl(this.series.id)
},
thumbnailUrl(): string {
return seriesThumbnailUrl(this.seriesId)
},