mirror of
https://github.com/gotson/komga.git
synced 2025-12-22 00:13:30 +01:00
feat(webui): action menu on item cards
This commit is contained in:
parent
08919814d3
commit
37d790d1fc
16 changed files with 294 additions and 57 deletions
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<v-menu offset-y>
|
||||
<v-menu offset-y v-model="menuState">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn icon v-on="on" @click.prevent="">
|
||||
<v-icon>mdi-dots-vertical</v-icon>
|
||||
|
|
@ -26,15 +26,30 @@
|
|||
<script lang="ts">
|
||||
import { getReadProgress } from '@/functions/book-progress'
|
||||
import { ReadStatus } from '@/types/enum-books'
|
||||
import { BOOK_CHANGED } from '@/types/events'
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'BookActionsMenu',
|
||||
data: () => {
|
||||
return {
|
||||
menuState: false,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
book: {
|
||||
type: Object as () => BookDto,
|
||||
required: true,
|
||||
},
|
||||
menu: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
menuState (val) {
|
||||
this.$emit('update:menu', val)
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isAdmin (): boolean {
|
||||
|
|
@ -57,11 +72,17 @@ export default Vue.extend({
|
|||
async markRead () {
|
||||
const readProgress = { completed: true } as ReadProgressUpdateDto
|
||||
await this.$komgaBooks.updateReadProgress(this.book.id, readProgress)
|
||||
this.$emit('mark-read', true)
|
||||
this.$eventHub.$emit(BOOK_CHANGED, {
|
||||
id: this.book.id,
|
||||
seriesId: this.book.seriesId,
|
||||
} as EventBookChanged)
|
||||
},
|
||||
async markUnread () {
|
||||
await this.$komgaBooks.deleteReadProgress(this.book.id)
|
||||
this.$emit('mark-unread', true)
|
||||
this.$eventHub.$emit(BOOK_CHANGED, {
|
||||
id: this.book.id,
|
||||
seriesId: this.book.seriesId,
|
||||
} as EventBookChanged)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<v-menu offset-y v-if="isAdmin">
|
||||
<v-menu offset-y v-if="isAdmin" v-model="menuState">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn icon v-on="on" @click.prevent="">
|
||||
<v-icon>mdi-dots-vertical</v-icon>
|
||||
|
|
@ -13,23 +13,16 @@
|
|||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
|
||||
<collection-delete-dialog v-model="modalDeleteCollection"
|
||||
:collection="collection"
|
||||
@deleted="afterDelete"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import CollectionDeleteDialog from '@/components/CollectionDeleteDialog.vue'
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'CollectionActionsMenu',
|
||||
components: { CollectionDeleteDialog },
|
||||
data: function () {
|
||||
return {
|
||||
modalDeleteCollection: false,
|
||||
menuState: false,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
|
|
@ -37,6 +30,15 @@ export default Vue.extend({
|
|||
type: Object as () => CollectionDto,
|
||||
required: true,
|
||||
},
|
||||
menu: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
menuState (val) {
|
||||
this.$emit('update:menu', val)
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isAdmin (): boolean {
|
||||
|
|
@ -45,10 +47,7 @@ export default Vue.extend({
|
|||
},
|
||||
methods: {
|
||||
promptDeleteCollection () {
|
||||
this.modalDeleteCollection = true
|
||||
},
|
||||
afterDelete () {
|
||||
this.$emit('deleted', true)
|
||||
this.$store.dispatch('dialogDeleteCollection', this.collection)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
|||
76
komga-webui/src/components/Dialogs.vue
Normal file
76
komga-webui/src/components/Dialogs.vue
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
<template>
|
||||
<div>
|
||||
<collection-add-to-dialog
|
||||
v-model="addToCollectionDialog"
|
||||
:series="addToCollectionSeries"
|
||||
@added="collectionAdded"
|
||||
/>
|
||||
|
||||
<collection-delete-dialog
|
||||
v-model="deleteCollectionDialog"
|
||||
:collection="deleteCollection"
|
||||
@deleted="collectionDeleted"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import CollectionAddToDialog from '@/components/CollectionAddToDialog.vue'
|
||||
import CollectionDeleteDialog from '@/components/CollectionDeleteDialog.vue'
|
||||
import { COLLECTION_CHANGED, SERIES_CHANGED } from '@/types/events'
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'Dialogs',
|
||||
components: { CollectionAddToDialog, CollectionDeleteDialog },
|
||||
computed: {
|
||||
addToCollectionDialog: {
|
||||
get (): boolean {
|
||||
return this.$store.state.addToCollectionDialog
|
||||
},
|
||||
set (val) {
|
||||
this.$store.dispatch('dialogAddSeriesToCollectionDisplay', val)
|
||||
},
|
||||
},
|
||||
addToCollectionSeries (): SeriesDto | SeriesDto[] {
|
||||
return this.$store.state.addToCollectionSeries
|
||||
},
|
||||
deleteCollectionDialog: {
|
||||
get (): boolean {
|
||||
return this.$store.state.deleteCollectionDialog
|
||||
},
|
||||
set (val) {
|
||||
this.$store.dispatch('dialogDeleteCollectionDisplay', val)
|
||||
},
|
||||
},
|
||||
deleteCollection (): CollectionDto {
|
||||
return this.$store.state.deleteCollection
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
collectionAdded () {
|
||||
if (Array.isArray(this.addToCollectionSeries)) {
|
||||
this.addToCollectionSeries.forEach(s => {
|
||||
this.$eventHub.$emit(SERIES_CHANGED, {
|
||||
id: s.id,
|
||||
libraryId: s.libraryId,
|
||||
} as EventSeriesChanged)
|
||||
})
|
||||
} else {
|
||||
this.$eventHub.$emit(SERIES_CHANGED, {
|
||||
id: this.addToCollectionSeries.id,
|
||||
libraryId: this.addToCollectionSeries.libraryId,
|
||||
} as EventSeriesChanged)
|
||||
}
|
||||
this.$eventHub.$emit(COLLECTION_CHANGED)
|
||||
},
|
||||
collectionDeleted () {
|
||||
this.$eventHub.$emit(COLLECTION_CHANGED)
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
|
@ -28,10 +28,10 @@
|
|||
<!-- Thumbnail overlay -->
|
||||
<v-fade-transition>
|
||||
<v-overlay
|
||||
v-if="hover || selected || preselect"
|
||||
v-if="hover || selected || preselect || actionMenuState"
|
||||
absolute
|
||||
:opacity="hover ? 0.3 : 0"
|
||||
:class="`${hover ? 'item-border-darken' : selected ? 'item-border' : 'item-border-transparent'} overlay-full`"
|
||||
:opacity="hover || actionMenuState ? 0.3 : 0"
|
||||
:class="`${hover || actionMenuState ? 'item-border-darken' : selected ? 'item-border' : 'item-border-transparent'} overlay-full`"
|
||||
>
|
||||
<!-- Circle icon for selection (top left) -->
|
||||
<v-icon v-if="onSelected"
|
||||
|
|
@ -56,12 +56,31 @@
|
|||
</v-btn>
|
||||
|
||||
<!-- Pen icon for edition (bottom left) -->
|
||||
<v-icon v-if="!selected && !preselect && onEdit"
|
||||
style="position: absolute; bottom: 10px; left: 10px"
|
||||
@click.stop="editItem"
|
||||
<v-btn icon
|
||||
v-if="!selected && !preselect && onEdit"
|
||||
style="position: absolute; bottom: 5px; left: 5px"
|
||||
@click.stop="editItem"
|
||||
>
|
||||
mdi-pencil
|
||||
</v-icon>
|
||||
<v-icon>mdi-pencil</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<!-- Action menu (bottom right) -->
|
||||
<div v-if="!selected && !preselect && actionMenu"
|
||||
style="position: absolute; bottom: 5px; right: 5px"
|
||||
>
|
||||
<book-actions-menu v-if="computedItem.type() === ItemTypes.BOOK"
|
||||
:book="item"
|
||||
:menu.sync="actionMenuState"
|
||||
/>
|
||||
<series-actions-menu v-if="computedItem.type() === ItemTypes.SERIES"
|
||||
:series="item"
|
||||
:menu.sync="actionMenuState"
|
||||
/>
|
||||
<collection-actions-menu v-if="computedItem.type() === ItemTypes.COLLECTION"
|
||||
:collection="item"
|
||||
:menu.sync="actionMenuState"
|
||||
/>
|
||||
</div>
|
||||
</v-overlay>
|
||||
</v-fade-transition>
|
||||
<v-progress-linear
|
||||
|
|
@ -90,6 +109,9 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import BookActionsMenu from '@/components/BookActionsMenu.vue'
|
||||
import CollectionActionsMenu from '@/components/CollectionActionsMenu.vue'
|
||||
import SeriesActionsMenu from '@/components/SeriesActionsMenu.vue'
|
||||
import { getReadProgress, getReadProgressPercentage } from '@/functions/book-progress'
|
||||
import { ReadStatus } from '@/types/enum-books'
|
||||
import { createItem, Item, ItemTypes } from '@/types/items'
|
||||
|
|
@ -97,6 +119,7 @@ import Vue from 'vue'
|
|||
|
||||
export default Vue.extend({
|
||||
name: 'ItemCard',
|
||||
components: { BookActionsMenu, SeriesActionsMenu, CollectionActionsMenu },
|
||||
props: {
|
||||
item: {
|
||||
type: Object as () => BookDto | SeriesDto | CollectionDto,
|
||||
|
|
@ -139,16 +162,24 @@ export default Vue.extend({
|
|||
default: undefined,
|
||||
required: false,
|
||||
},
|
||||
// action menu enabled or not
|
||||
actionMenu: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data: () => {
|
||||
return {}
|
||||
return {
|
||||
ItemTypes,
|
||||
actionMenuState: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
canReadPages (): boolean {
|
||||
return this.$store.getters.mePageStreaming && this.computedItem.type() === ItemTypes.BOOK
|
||||
},
|
||||
overlay (): boolean {
|
||||
return this.onEdit !== undefined || this.onSelected !== undefined || this.bookReady || this.canReadPages
|
||||
return this.onEdit !== undefined || this.onSelected !== undefined || this.bookReady || this.canReadPages || this.actionMenu
|
||||
},
|
||||
computedItem (): Item<BookDto | SeriesDto | CollectionDto> {
|
||||
return createItem(this.item)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<v-menu offset-y>
|
||||
<v-menu offset-y v-model="menuState">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn icon v-on="on" @click.prevent="">
|
||||
<v-icon>mdi-dots-vertical</v-icon>
|
||||
|
|
@ -27,15 +27,30 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { SERIES_CHANGED } from '@/types/events'
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'SeriesActionsMenu',
|
||||
data: () => {
|
||||
return {
|
||||
menuState: false,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
series: {
|
||||
type: Object as () => SeriesDto,
|
||||
required: true,
|
||||
},
|
||||
menu: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
menuState (val) {
|
||||
this.$emit('update:menu', val)
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isAdmin (): boolean {
|
||||
|
|
@ -56,15 +71,21 @@ export default Vue.extend({
|
|||
this.$komgaSeries.refreshMetadata(this.series)
|
||||
},
|
||||
addToCollection () {
|
||||
this.$emit('add-to-collection', true)
|
||||
this.$store.dispatch('dialogAddSeriesToCollection', this.series)
|
||||
},
|
||||
async markRead () {
|
||||
await this.$komgaSeries.markAsRead(this.series.id)
|
||||
this.$emit('mark-read', true)
|
||||
this.$eventHub.$emit(SERIES_CHANGED, {
|
||||
id: this.series.id,
|
||||
libraryId: this.series.libraryId,
|
||||
} as EventSeriesChanged)
|
||||
},
|
||||
async markUnread () {
|
||||
await this.$komgaSeries.markAsUnread(this.series.id)
|
||||
this.$emit('mark-unread', true)
|
||||
this.$eventHub.$emit(SERIES_CHANGED, {
|
||||
id: this.series.id,
|
||||
libraryId: this.series.libraryId,
|
||||
} as EventSeriesChanged)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ Vue.use(komgaLibraries, { store: store, http: Vue.prototype.$http })
|
|||
Vue.use(actuator, { http: Vue.prototype.$http })
|
||||
|
||||
Vue.prototype.$_ = _
|
||||
Vue.prototype.$eventHub = new Vue()
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
|
|
@ -51,6 +52,7 @@ new Vue({
|
|||
declare module 'vue/types/vue' {
|
||||
interface Vue {
|
||||
$_: LoDashStatic;
|
||||
$eventHub: Vue;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,40 @@ import Vuex from 'vuex'
|
|||
Vue.use(Vuex)
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: {},
|
||||
mutations: {},
|
||||
actions: {},
|
||||
state: {
|
||||
addToCollectionSeries: {} as SeriesDto | SeriesDto[],
|
||||
addToCollectionDialog: false,
|
||||
deleteCollection: {} as CollectionDto,
|
||||
deleteCollectionDialog: false,
|
||||
},
|
||||
mutations: {
|
||||
setAddToCollectionSeries (state, series) {
|
||||
state.addToCollectionSeries = series
|
||||
},
|
||||
setAddToCollectionDialog (state, dialog) {
|
||||
state.addToCollectionDialog = dialog
|
||||
},
|
||||
setDeleteCollection (state, collection) {
|
||||
state.deleteCollection = collection
|
||||
},
|
||||
setDeleteCollectionDialog (state, dialog) {
|
||||
state.deleteCollectionDialog = dialog
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
dialogAddSeriesToCollection ({ commit }, series) {
|
||||
commit('setAddToCollectionSeries', series)
|
||||
commit('setAddToCollectionDialog', true)
|
||||
},
|
||||
dialogAddSeriesToCollectionDisplay ({ commit }, value) {
|
||||
commit('setAddToCollectionDialog', value)
|
||||
},
|
||||
dialogDeleteCollection ({ commit }, collection) {
|
||||
commit('setDeleteCollection', collection)
|
||||
commit('setDeleteCollectionDialog', true)
|
||||
},
|
||||
dialogDeleteCollectionDisplay ({ commit }, value) {
|
||||
commit('setDeleteCollectionDialog', value)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
|||
9
komga-webui/src/types/events-payloads.ts
Normal file
9
komga-webui/src/types/events-payloads.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
interface EventBookChanged {
|
||||
id: number,
|
||||
seriesId: number
|
||||
}
|
||||
|
||||
interface EventSeriesChanged {
|
||||
id: number,
|
||||
libraryId: number
|
||||
}
|
||||
3
komga-webui/src/types/events.ts
Normal file
3
komga-webui/src/types/events.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export const BOOK_CHANGED = 'book-changed'
|
||||
export const SERIES_CHANGED = 'series-changed'
|
||||
export const COLLECTION_CHANGED = 'collection-changed'
|
||||
|
|
@ -253,7 +253,6 @@ import SettingsSelect from '@/components/SettingsSelect.vue'
|
|||
import SettingsSwitch from '@/components/SettingsSwitch.vue'
|
||||
import ThumbnailExplorerDialog from '@/components/ThumbnailExplorerDialog.vue'
|
||||
import { getBookTitleCompact } from '@/functions/book-title'
|
||||
|
||||
import { checkWebpFeature } from '@/functions/check-webp'
|
||||
import { bookPageUrl } from '@/functions/urls'
|
||||
import { ReadingDirection } from '@/types/enum-books'
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@
|
|||
<!-- Action menu -->
|
||||
<book-actions-menu v-if="book"
|
||||
:book="book"
|
||||
@mark-read="loadBook(bookId)"
|
||||
@mark-unread="loadBook(bookId)"
|
||||
/>
|
||||
</toolbar-sticky>
|
||||
|
||||
|
|
@ -32,6 +30,7 @@
|
|||
:item="book"
|
||||
thumbnail-only
|
||||
no-link
|
||||
:action-menu="false"
|
||||
></item-card>
|
||||
</v-col>
|
||||
|
||||
|
|
@ -158,6 +157,7 @@ import { getReadProgress, getReadProgressPercentage } from '@/functions/book-pro
|
|||
import { getBookTitleCompact } from '@/functions/book-title'
|
||||
import { bookFileUrl, bookThumbnailUrl } from '@/functions/urls'
|
||||
import { ReadStatus } from '@/types/enum-books'
|
||||
import { BOOK_CHANGED } from '@/types/events'
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
|
|
@ -172,6 +172,10 @@ export default Vue.extend({
|
|||
},
|
||||
async created () {
|
||||
this.loadBook(this.bookId)
|
||||
this.$eventHub.$on(BOOK_CHANGED, this.reloadBook)
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$eventHub.$off(BOOK_CHANGED, this.reloadBook)
|
||||
},
|
||||
watch: {
|
||||
async book (val) {
|
||||
|
|
@ -230,6 +234,9 @@ export default Vue.extend({
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
reloadBook (event: EventBookChanged) {
|
||||
if (event.id === this.bookId) this.loadBook(this.bookId)
|
||||
},
|
||||
async loadBook (bookId: number) {
|
||||
this.book = await this.$komgaBooks.getBook(bookId)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
<collection-actions-menu v-if="collection"
|
||||
:collection="collection"
|
||||
@deleted="afterDelete"
|
||||
/>
|
||||
|
||||
<v-toolbar-title v-if="collection">
|
||||
|
|
@ -141,6 +140,7 @@ import CollectionEditDialog from '@/components/CollectionEditDialog.vue'
|
|||
import EditSeriesDialog from '@/components/EditSeriesDialog.vue'
|
||||
import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||
import ToolbarSticky from '@/components/ToolbarSticky.vue'
|
||||
import { COLLECTION_CHANGED } from '@/types/events'
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
|
|
@ -203,6 +203,12 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
},
|
||||
created () {
|
||||
this.$eventHub.$on(COLLECTION_CHANGED, this.afterDelete)
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$eventHub.$off(COLLECTION_CHANGED, this.afterDelete)
|
||||
},
|
||||
mounted () {
|
||||
this.loadCollection(this.collectionId)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import ItemBrowser from '@/components/ItemBrowser.vue'
|
|||
import LibraryActionsMenu from '@/components/LibraryActionsMenu.vue'
|
||||
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
||||
import ToolbarSticky from '@/components/ToolbarSticky.vue'
|
||||
import { COLLECTION_CHANGED } from '@/types/events'
|
||||
import Vue from 'vue'
|
||||
|
||||
const cookiePageSize = 'pagesize'
|
||||
|
|
@ -56,6 +57,12 @@ export default Vue.extend({
|
|||
default: 0,
|
||||
},
|
||||
},
|
||||
created () {
|
||||
this.$eventHub.$on(COLLECTION_CHANGED, this.reloadCollections)
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCollections)
|
||||
},
|
||||
mounted () {
|
||||
this.loadLibrary(this.libraryId)
|
||||
},
|
||||
|
|
@ -75,10 +82,16 @@ export default Vue.extend({
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
reloadCollections () {
|
||||
this.loadLibrary(this.libraryId)
|
||||
},
|
||||
async loadLibrary (libraryId: number) {
|
||||
this.library = this.getLibraryLazy(libraryId)
|
||||
const lib = libraryId !== 0 ? [libraryId] : undefined
|
||||
this.collections = await this.$komgaCollections.getCollections(lib)
|
||||
if (this.collections.length === 0) {
|
||||
await this.$router.push({ name: 'browse-libraries', params: { libraryId: libraryId.toString() } })
|
||||
}
|
||||
},
|
||||
getLibraryLazy (libraryId: any): LibraryDto | undefined {
|
||||
if (libraryId !== 0) {
|
||||
|
|
|
|||
|
|
@ -89,10 +89,6 @@
|
|||
:series.sync="editSeriesSingle"
|
||||
/>
|
||||
|
||||
<collection-add-to-dialog v-model="dialogAddToCollection"
|
||||
:series="selectedSeries"
|
||||
/>
|
||||
|
||||
<v-container fluid class="px-6">
|
||||
<empty-state
|
||||
v-if="totalPages === 0"
|
||||
|
|
@ -124,7 +120,6 @@
|
|||
|
||||
<script lang="ts">
|
||||
import Badge from '@/components/Badge.vue'
|
||||
import CollectionAddToDialog from '@/components/CollectionAddToDialog.vue'
|
||||
import EditSeriesDialog from '@/components/EditSeriesDialog.vue'
|
||||
import EmptyState from '@/components/EmptyState.vue'
|
||||
import FilterMenuButton from '@/components/FilterMenuButton.vue'
|
||||
|
|
@ -137,6 +132,7 @@ import ToolbarSticky from '@/components/ToolbarSticky.vue'
|
|||
import { parseQueryFilter, parseQuerySort } from '@/functions/query-params'
|
||||
import { ReadStatus } from '@/types/enum-books'
|
||||
import { SeriesStatus } from '@/types/enum-series'
|
||||
import { COLLECTION_CHANGED, SERIES_CHANGED } from '@/types/events'
|
||||
import Vue from 'vue'
|
||||
|
||||
const cookiePageSize = 'pagesize'
|
||||
|
|
@ -152,7 +148,6 @@ export default Vue.extend({
|
|||
Badge,
|
||||
EditSeriesDialog,
|
||||
ItemBrowser,
|
||||
CollectionAddToDialog,
|
||||
PageSizeSelect,
|
||||
LibraryNavigation,
|
||||
},
|
||||
|
|
@ -212,6 +207,14 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
},
|
||||
created () {
|
||||
this.$eventHub.$on(COLLECTION_CHANGED, this.reloadCollections)
|
||||
this.$eventHub.$on(SERIES_CHANGED, this.reloadSeries)
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCollections)
|
||||
this.$eventHub.$off(SERIES_CHANGED, this.reloadSeries)
|
||||
},
|
||||
mounted () {
|
||||
if (this.$cookies.isKey(cookiePageSize)) {
|
||||
this.pageSize = Number(this.$cookies.get(cookiePageSize))
|
||||
|
|
@ -298,6 +301,14 @@ export default Vue.extend({
|
|||
|
||||
this.setWatches()
|
||||
},
|
||||
reloadCollections () {
|
||||
this.loadLibrary(this.libraryId)
|
||||
},
|
||||
reloadSeries (event: EventSeriesChanged) {
|
||||
if (this.libraryId === 0 || event.libraryId === this.libraryId) {
|
||||
this.loadPage(this.libraryId, this.page, this.sortActive)
|
||||
}
|
||||
},
|
||||
async loadLibrary (libraryId: number) {
|
||||
this.library = this.getLibraryLazy(libraryId)
|
||||
|
||||
|
|
@ -371,7 +382,7 @@ export default Vue.extend({
|
|||
))
|
||||
},
|
||||
addToCollection () {
|
||||
this.dialogAddToCollection = true
|
||||
this.$store.dispatch('dialogAddSeriesToCollection', this.selectedSeries)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -11,9 +11,6 @@
|
|||
|
||||
<series-actions-menu v-if="series"
|
||||
:series="series"
|
||||
@add-to-collection="addToCollection"
|
||||
@mark-read="loadSeries(seriesId)"
|
||||
@mark-unread="loadSeries(seriesId)"
|
||||
/>
|
||||
|
||||
<v-toolbar-title>
|
||||
|
|
@ -94,6 +91,7 @@
|
|||
:item="series"
|
||||
thumbnail-only
|
||||
no-link
|
||||
:action-menu="false"
|
||||
></item-card>
|
||||
|
||||
</v-col>
|
||||
|
|
@ -194,16 +192,11 @@
|
|||
|
||||
<edit-series-dialog v-model="dialogEdit" :series.sync="series"/>
|
||||
|
||||
<collection-add-to-dialog v-model="dialogAddToCollection"
|
||||
:series="series"
|
||||
@added="loadSeries(seriesId)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Badge from '@/components/Badge.vue'
|
||||
import CollectionAddToDialog from '@/components/CollectionAddToDialog.vue'
|
||||
import EditBooksDialog from '@/components/EditBooksDialog.vue'
|
||||
import EditSeriesDialog from '@/components/EditSeriesDialog.vue'
|
||||
import EmptyState from '@/components/EmptyState.vue'
|
||||
|
|
@ -218,6 +211,7 @@ import ToolbarSticky from '@/components/ToolbarSticky.vue'
|
|||
import { parseQueryFilter, parseQuerySort } from '@/functions/query-params'
|
||||
import { seriesThumbnailUrl } from '@/functions/urls'
|
||||
import { ReadStatus } from '@/types/enum-books'
|
||||
import { BOOK_CHANGED, SERIES_CHANGED } from '@/types/events'
|
||||
import Vue from 'vue'
|
||||
|
||||
const cookiePageSize = 'pagesize'
|
||||
|
|
@ -234,7 +228,6 @@ export default Vue.extend({
|
|||
ItemBrowser,
|
||||
PageSizeSelect,
|
||||
SeriesActionsMenu,
|
||||
CollectionAddToDialog,
|
||||
HorizontalScroller,
|
||||
ItemCard,
|
||||
EmptyState,
|
||||
|
|
@ -323,6 +316,14 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
},
|
||||
created () {
|
||||
this.$eventHub.$on(SERIES_CHANGED, this.reloadSeries)
|
||||
this.$eventHub.$on(BOOK_CHANGED, this.reloadBooks)
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$eventHub.$off(SERIES_CHANGED, this.reloadSeries)
|
||||
this.$eventHub.$on(BOOK_CHANGED, this.reloadBooks)
|
||||
},
|
||||
mounted () {
|
||||
if (this.$cookies.isKey(cookiePageSize)) {
|
||||
this.pageSize = Number(this.$cookies.get(cookiePageSize))
|
||||
|
|
@ -390,6 +391,12 @@ export default Vue.extend({
|
|||
|
||||
this.setWatches()
|
||||
},
|
||||
reloadSeries (event: EventSeriesChanged) {
|
||||
if (event.id === this.seriesId) this.loadSeries(this.seriesId)
|
||||
},
|
||||
reloadBooks (event: EventBookChanged) {
|
||||
if (event.seriesId === this.seriesId) this.loadSeries(this.seriesId)
|
||||
},
|
||||
async loadSeries (seriesId: number) {
|
||||
this.series = await this.$komgaSeries.getOneSeries(seriesId)
|
||||
this.collections = await this.$komgaSeries.getCollections(seriesId)
|
||||
|
|
@ -460,9 +467,6 @@ export default Vue.extend({
|
|||
))
|
||||
this.loadSeries(this.seriesId)
|
||||
},
|
||||
addToCollection () {
|
||||
this.dialogAddToCollection = true
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -109,19 +109,21 @@
|
|||
</v-navigation-drawer>
|
||||
|
||||
<v-content>
|
||||
<dialogs/>
|
||||
<router-view/>
|
||||
</v-content>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Dialogs from '@/components/Dialogs.vue'
|
||||
import LibraryActionsMenu from '@/components/LibraryActionsMenu.vue'
|
||||
import SearchBox from '@/components/SearchBox.vue'
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'home',
|
||||
components: { LibraryActionsMenu, SearchBox },
|
||||
components: { LibraryActionsMenu, SearchBox, Dialogs },
|
||||
data: function () {
|
||||
return {
|
||||
drawerVisible: this.$vuetify.breakpoint.lgAndUp,
|
||||
|
|
|
|||
Loading…
Reference in a new issue