mirror of
https://github.com/gotson/komga.git
synced 2026-05-09 05:10:19 +02:00
feat(webui): the UI is now dynamic to events from the server
closes #124
This commit is contained in:
parent
691c7f0071
commit
a707fd3594
37 changed files with 741 additions and 330 deletions
|
|
@ -6,6 +6,8 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {Theme} from "@/types/themes";
|
import {Theme} from "@/types/themes";
|
||||||
|
import {LIBRARY_ADDED, LIBRARY_CHANGED, LIBRARY_DELETED} from "@/types/events";
|
||||||
|
import {LibrarySseDto} from "@/types/komga-sse";
|
||||||
|
|
||||||
const cookieLocale = 'locale'
|
const cookieLocale = 'locale'
|
||||||
const cookieTheme = 'theme'
|
const cookieTheme = 'theme'
|
||||||
|
|
@ -73,9 +75,18 @@ export default Vue.extend({
|
||||||
this.$cookies.keys()
|
this.$cookies.keys()
|
||||||
.filter(x => x.startsWith('collection.filter') || x.startsWith('library.filter') || x.startsWith('library.sort'))
|
.filter(x => x.startsWith('collection.filter') || x.startsWith('library.filter') || x.startsWith('library.sort'))
|
||||||
.forEach(x => this.$cookies.remove(x))
|
.forEach(x => this.$cookies.remove(x))
|
||||||
|
|
||||||
|
|
||||||
|
this.$eventHub.$on(LIBRARY_ADDED, this.reloadLibraries)
|
||||||
|
this.$eventHub.$on(LIBRARY_DELETED, this.reloadLibraries)
|
||||||
|
this.$eventHub.$on(LIBRARY_CHANGED, this.reloadLibraries)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', this.systemThemeChange)
|
window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', this.systemThemeChange)
|
||||||
|
|
||||||
|
this.$eventHub.$off(LIBRARY_ADDED, this.reloadLibraries)
|
||||||
|
this.$eventHub.$off(LIBRARY_DELETED, this.reloadLibraries)
|
||||||
|
this.$eventHub.$off(LIBRARY_CHANGED, this.reloadLibraries)
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
"$store.state.persistedState.locale": {
|
"$store.state.persistedState.locale": {
|
||||||
|
|
@ -117,6 +128,9 @@ export default Vue.extend({
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
reloadLibraries(event: LibrarySseDto) {
|
||||||
|
this.$store.dispatch('getLibraries')
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -3,39 +3,31 @@
|
||||||
<collection-add-to-dialog
|
<collection-add-to-dialog
|
||||||
v-model="addToCollectionDialog"
|
v-model="addToCollectionDialog"
|
||||||
:series="addToCollectionSeries"
|
:series="addToCollectionSeries"
|
||||||
@added="collectionAdded"
|
|
||||||
@created="collectionAdded"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<collection-edit-dialog
|
<collection-edit-dialog
|
||||||
v-model="editCollectionDialog"
|
v-model="editCollectionDialog"
|
||||||
:collection="editCollection"
|
:collection="editCollection"
|
||||||
@updated="collectionUpdated"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<collection-delete-dialog
|
<collection-delete-dialog
|
||||||
v-model="deleteCollectionDialog"
|
v-model="deleteCollectionDialog"
|
||||||
:collection="deleteCollection"
|
:collection="deleteCollection"
|
||||||
@deleted="collectionDeleted"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<read-list-add-to-dialog
|
<read-list-add-to-dialog
|
||||||
v-model="addToReadListDialog"
|
v-model="addToReadListDialog"
|
||||||
:books="addToReadListBooks"
|
:books="addToReadListBooks"
|
||||||
@added="readListAdded"
|
|
||||||
@created="readListAdded"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<read-list-edit-dialog
|
<read-list-edit-dialog
|
||||||
v-model="editReadListDialog"
|
v-model="editReadListDialog"
|
||||||
:read-list="editReadList"
|
:read-list="editReadList"
|
||||||
@updated="readListUpdated"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<read-list-delete-dialog
|
<read-list-delete-dialog
|
||||||
v-model="deleteReadListDialog"
|
v-model="deleteReadListDialog"
|
||||||
:read-list="deleteReadList"
|
:read-list="deleteReadList"
|
||||||
@deleted="readListDeleted"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<library-edit-dialog
|
<library-edit-dialog
|
||||||
|
|
@ -46,19 +38,16 @@
|
||||||
<library-delete-dialog
|
<library-delete-dialog
|
||||||
v-model="deleteLibraryDialog"
|
v-model="deleteLibraryDialog"
|
||||||
:library="deleteLibrary"
|
:library="deleteLibrary"
|
||||||
@deleted="libraryDeleted"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<edit-books-dialog
|
<edit-books-dialog
|
||||||
v-model="updateBooksDialog"
|
v-model="updateBooksDialog"
|
||||||
:books="updateBooks"
|
:books="updateBooks"
|
||||||
@updated="bookUpdated"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<edit-series-dialog
|
<edit-series-dialog
|
||||||
v-model="updateSeriesDialog"
|
v-model="updateSeriesDialog"
|
||||||
:series="updateSeries"
|
:series="updateSeries"
|
||||||
@updated="seriesUpdated"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -72,27 +61,11 @@ import EditBooksDialog from '@/components/dialogs/EditBooksDialog.vue'
|
||||||
import EditSeriesDialog from '@/components/dialogs/EditSeriesDialog.vue'
|
import EditSeriesDialog from '@/components/dialogs/EditSeriesDialog.vue'
|
||||||
import LibraryDeleteDialog from '@/components/dialogs/LibraryDeleteDialog.vue'
|
import LibraryDeleteDialog from '@/components/dialogs/LibraryDeleteDialog.vue'
|
||||||
import LibraryEditDialog from '@/components/dialogs/LibraryEditDialog.vue'
|
import LibraryEditDialog from '@/components/dialogs/LibraryEditDialog.vue'
|
||||||
import {
|
|
||||||
BOOK_CHANGED,
|
|
||||||
bookToEventBookChanged,
|
|
||||||
COLLECTION_CHANGED,
|
|
||||||
COLLECTION_DELETED,
|
|
||||||
collectionToEventCollectionChanged,
|
|
||||||
collectionToEventCollectionDeleted,
|
|
||||||
LIBRARY_DELETED,
|
|
||||||
libraryToEventLibraryDeleted,
|
|
||||||
READLIST_CHANGED,
|
|
||||||
READLIST_DELETED,
|
|
||||||
readListToEventReadListChanged,
|
|
||||||
readListToEventReadListDeleted,
|
|
||||||
SERIES_CHANGED,
|
|
||||||
seriesToEventSeriesChanged,
|
|
||||||
} from '@/types/events'
|
|
||||||
import Vue from 'vue'
|
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'
|
import {BookDto} from '@/types/komga-books'
|
||||||
import {SeriesDto} from "@/types/komga-series";
|
import {SeriesDto} from "@/types/komga-series";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
|
|
@ -226,49 +199,6 @@ export default Vue.extend({
|
||||||
return this.$store.state.updateSeries
|
return this.$store.state.updateSeries
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
collectionAdded (collection: CollectionDto) {
|
|
||||||
if (Array.isArray(this.addToCollectionSeries)) {
|
|
||||||
this.addToCollectionSeries.forEach(s => {
|
|
||||||
this.$eventHub.$emit(SERIES_CHANGED, seriesToEventSeriesChanged(s))
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.$eventHub.$emit(SERIES_CHANGED, seriesToEventSeriesChanged(this.addToCollectionSeries))
|
|
||||||
}
|
|
||||||
this.$eventHub.$emit(COLLECTION_CHANGED, collectionToEventCollectionChanged(collection))
|
|
||||||
},
|
|
||||||
collectionUpdated () {
|
|
||||||
this.$eventHub.$emit(COLLECTION_CHANGED, collectionToEventCollectionChanged(this.editCollection))
|
|
||||||
},
|
|
||||||
collectionDeleted () {
|
|
||||||
this.$eventHub.$emit(COLLECTION_DELETED, collectionToEventCollectionDeleted(this.deleteCollection))
|
|
||||||
},
|
|
||||||
readListAdded (readList: ReadListDto) {
|
|
||||||
if (Array.isArray(this.addToReadListBooks)) {
|
|
||||||
this.addToReadListBooks.forEach(b => {
|
|
||||||
this.$eventHub.$emit(BOOK_CHANGED, bookToEventBookChanged(b))
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.$eventHub.$emit(BOOK_CHANGED, bookToEventBookChanged(this.addToReadListBooks))
|
|
||||||
}
|
|
||||||
this.$eventHub.$emit(READLIST_CHANGED, readListToEventReadListChanged(readList))
|
|
||||||
},
|
|
||||||
readListUpdated () {
|
|
||||||
this.$eventHub.$emit(READLIST_CHANGED, readListToEventReadListChanged(this.editReadList))
|
|
||||||
},
|
|
||||||
readListDeleted () {
|
|
||||||
this.$eventHub.$emit(READLIST_DELETED, readListToEventReadListDeleted(this.deleteReadList))
|
|
||||||
},
|
|
||||||
libraryDeleted () {
|
|
||||||
this.$eventHub.$emit(LIBRARY_DELETED, libraryToEventLibraryDeleted(this.deleteLibrary))
|
|
||||||
},
|
|
||||||
bookUpdated (book: BookDto) {
|
|
||||||
this.$eventHub.$emit(BOOK_CHANGED, bookToEventBookChanged(book))
|
|
||||||
},
|
|
||||||
seriesUpdated (series: SeriesDto) {
|
|
||||||
this.$eventHub.$emit(SERIES_CHANGED, seriesToEventSeriesChanged(series))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
lazy-src="../assets/cover.svg"
|
lazy-src="../assets/cover.svg"
|
||||||
aspect-ratio="0.7071"
|
aspect-ratio="0.7071"
|
||||||
contain
|
contain
|
||||||
|
@error="thumbnailError = true"
|
||||||
>
|
>
|
||||||
<!-- unread tick for book -->
|
<!-- unread tick for book -->
|
||||||
<div class="unread" v-if="isUnread"/>
|
<div class="unread" v-if="isUnread"/>
|
||||||
|
|
@ -39,7 +40,8 @@
|
||||||
:style="'position: absolute; top: 5px; ' + ($vuetify.rtl ? 'right' : 'left') + ': 10px'"
|
:style="'position: absolute; top: 5px; ' + ($vuetify.rtl ? 'right' : 'left') + ': 10px'"
|
||||||
@click.stop="selectItem"
|
@click.stop="selectItem"
|
||||||
>
|
>
|
||||||
{{ selected || (preselect && hover) ? 'mdi-checkbox-marked-circle' : 'mdi-checkbox-blank-circle-outline'
|
{{
|
||||||
|
selected || (preselect && hover) ? 'mdi-checkbox-marked-circle' : 'mdi-checkbox-blank-circle-outline'
|
||||||
}}
|
}}
|
||||||
</v-icon>
|
</v-icon>
|
||||||
|
|
||||||
|
|
@ -126,10 +128,12 @@ 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'
|
import {BookDto} from '@/types/komga-books'
|
||||||
import {SeriesDto} from "@/types/komga-series";
|
import {SeriesDto} from "@/types/komga-series";
|
||||||
|
import {THUMBNAILBOOK_ADDED, THUMBNAILSERIES_ADDED} from "@/types/events";
|
||||||
|
import {ThumbnailBookSseDto, ThumbnailSeriesSseDto} from "@/types/komga-sse";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'ItemCard',
|
name: 'ItemCard',
|
||||||
components: { BookActionsMenu, SeriesActionsMenu, CollectionActionsMenu, ReadListActionsMenu },
|
components: {BookActionsMenu, SeriesActionsMenu, CollectionActionsMenu, ReadListActionsMenu},
|
||||||
props: {
|
props: {
|
||||||
item: {
|
item: {
|
||||||
type: Object as () => BookDto | SeriesDto | CollectionDto | ReadListDto,
|
type: Object as () => BookDto | SeriesDto | CollectionDto | ReadListDto,
|
||||||
|
|
@ -182,79 +186,101 @@ export default Vue.extend({
|
||||||
return {
|
return {
|
||||||
ItemTypes,
|
ItemTypes,
|
||||||
actionMenuState: false,
|
actionMenuState: false,
|
||||||
|
thumbnailError: false,
|
||||||
|
thumbnailCacheBust: '',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
this.$eventHub.$on(THUMBNAILBOOK_ADDED, this.thumbnailBookAdded)
|
||||||
|
this.$eventHub.$on(THUMBNAILSERIES_ADDED, this.thumbnailSeriesAdded)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.$eventHub.$off(THUMBNAILBOOK_ADDED, this.thumbnailBookAdded)
|
||||||
|
this.$eventHub.$off(THUMBNAILSERIES_ADDED, this.thumbnailSeriesAdded)
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
canReadPages (): boolean {
|
canReadPages(): boolean {
|
||||||
return this.$store.getters.mePageStreaming && this.computedItem.type() === ItemTypes.BOOK
|
return this.$store.getters.mePageStreaming && this.computedItem.type() === ItemTypes.BOOK
|
||||||
},
|
},
|
||||||
overlay (): boolean {
|
overlay(): boolean {
|
||||||
return this.onEdit !== undefined || this.onSelected !== undefined || this.bookReady || this.canReadPages || this.actionMenu
|
return this.onEdit !== undefined || this.onSelected !== undefined || this.bookReady || this.canReadPages || this.actionMenu
|
||||||
},
|
},
|
||||||
computedItem (): Item<BookDto | SeriesDto | CollectionDto | ReadListDto> {
|
computedItem(): Item<BookDto | SeriesDto | CollectionDto | ReadListDto> {
|
||||||
return createItem(this.item)
|
return createItem(this.item)
|
||||||
},
|
},
|
||||||
disableHover (): boolean {
|
disableHover(): boolean {
|
||||||
return !this.overlay
|
return !this.overlay
|
||||||
},
|
},
|
||||||
thumbnailUrl (): string {
|
thumbnailUrl(): string {
|
||||||
return this.computedItem.thumbnailUrl()
|
return this.computedItem.thumbnailUrl() + this.thumbnailCacheBust
|
||||||
},
|
},
|
||||||
title (): string {
|
title(): string {
|
||||||
return this.computedItem.title()
|
return this.computedItem.title()
|
||||||
},
|
},
|
||||||
subtitleProps (): Object {
|
subtitleProps(): Object {
|
||||||
return this.computedItem.subtitleProps()
|
return this.computedItem.subtitleProps()
|
||||||
},
|
},
|
||||||
body (): string {
|
body(): string {
|
||||||
return this.computedItem.body()
|
return this.computedItem.body()
|
||||||
},
|
},
|
||||||
isInProgress (): boolean {
|
isInProgress(): boolean {
|
||||||
if (this.computedItem.type() === ItemTypes.BOOK) return getReadProgress(this.item as BookDto) === ReadStatus.IN_PROGRESS
|
if (this.computedItem.type() === ItemTypes.BOOK) return getReadProgress(this.item as BookDto) === ReadStatus.IN_PROGRESS
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
isUnread (): boolean {
|
isUnread(): boolean {
|
||||||
if (this.computedItem.type() === ItemTypes.BOOK) return getReadProgress(this.item as BookDto) === ReadStatus.UNREAD
|
if (this.computedItem.type() === ItemTypes.BOOK) return getReadProgress(this.item as BookDto) === ReadStatus.UNREAD
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
unreadCount (): number | undefined {
|
unreadCount(): number | undefined {
|
||||||
if (this.computedItem.type() === ItemTypes.SERIES) return (this.item as SeriesDto).booksUnreadCount + (this.item as SeriesDto).booksInProgressCount
|
if (this.computedItem.type() === ItemTypes.SERIES) return (this.item as SeriesDto).booksUnreadCount + (this.item as SeriesDto).booksInProgressCount
|
||||||
return undefined
|
return undefined
|
||||||
},
|
},
|
||||||
readProgressPercentage (): number {
|
readProgressPercentage(): number {
|
||||||
if (this.computedItem.type() === ItemTypes.BOOK) return getReadProgressPercentage(this.item as BookDto)
|
if (this.computedItem.type() === ItemTypes.BOOK) return getReadProgressPercentage(this.item as BookDto)
|
||||||
return 0
|
return 0
|
||||||
},
|
},
|
||||||
bookReady (): boolean {
|
bookReady(): boolean {
|
||||||
if (this.computedItem.type() === ItemTypes.BOOK) {
|
if (this.computedItem.type() === ItemTypes.BOOK) {
|
||||||
return (this.item as BookDto).media.status === 'READY'
|
return (this.item as BookDto).media.status === 'READY'
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
to (): RawLocation {
|
to(): RawLocation {
|
||||||
return this.computedItem.to()
|
return this.computedItem.to()
|
||||||
},
|
},
|
||||||
fabTo (): RawLocation {
|
fabTo(): RawLocation {
|
||||||
return this.computedItem.fabTo()
|
return this.computedItem.fabTo()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onClick () {
|
thumbnailBookAdded(event: ThumbnailBookSseDto) {
|
||||||
|
if (this.thumbnailError &&
|
||||||
|
((this.computedItem.type() === ItemTypes.BOOK && event.bookId === this.item.id) || (this.computedItem.type() === ItemTypes.SERIES && event.seriesId === this.item.id))
|
||||||
|
) {
|
||||||
|
this.thumbnailCacheBust = '?' + this.$_.random(1000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
thumbnailSeriesAdded(event: ThumbnailSeriesSseDto) {
|
||||||
|
if (this.thumbnailError && (this.computedItem.type() === ItemTypes.SERIES && event.seriesId === this.item.id)) {
|
||||||
|
this.thumbnailCacheBust = '?' + this.$_.random(1000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClick() {
|
||||||
if (this.preselect && this.onSelected !== undefined) {
|
if (this.preselect && this.onSelected !== undefined) {
|
||||||
this.selectItem()
|
this.selectItem()
|
||||||
} else if (!this.noLink) {
|
} else if (!this.noLink) {
|
||||||
this.goto()
|
this.goto()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
goto () {
|
goto() {
|
||||||
this.$router.push(this.computedItem.to())
|
this.$router.push(this.computedItem.to())
|
||||||
},
|
},
|
||||||
selectItem () {
|
selectItem() {
|
||||||
if (this.onSelected !== undefined) {
|
if (this.onSelected !== undefined) {
|
||||||
this.onSelected()
|
this.onSelected()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
editItem () {
|
editItem() {
|
||||||
if (this.onEdit !== undefined) {
|
if (this.onEdit !== undefined) {
|
||||||
this.onEdit(this.item)
|
this.onEdit(this.item)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {COLLECTION_CHANGED, READLIST_CHANGED} from '@/types/events'
|
import {COLLECTION_ADDED, COLLECTION_DELETED, READLIST_ADDED, READLIST_DELETED} from '@/types/events'
|
||||||
import {LIBRARIES_ALL} from '@/types/library'
|
import {LIBRARIES_ALL} from '@/types/library'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
|
|
@ -101,18 +101,23 @@ export default Vue.extend({
|
||||||
watch: {
|
watch: {
|
||||||
libraryId: {
|
libraryId: {
|
||||||
handler(val) {
|
handler(val) {
|
||||||
this.loadCounts(val)
|
this.loadReadListCounts(val)
|
||||||
|
this.loadCollectionCounts(val)
|
||||||
},
|
},
|
||||||
immediate: true,
|
immediate: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$eventHub.$on(COLLECTION_CHANGED, this.reloadCounts)
|
this.$eventHub.$on(COLLECTION_ADDED, this.collectionAdded)
|
||||||
this.$eventHub.$on(READLIST_CHANGED, this.reloadCounts)
|
this.$eventHub.$on(COLLECTION_DELETED, this.collectionDeleted)
|
||||||
|
this.$eventHub.$on(READLIST_ADDED, this.readListAdded)
|
||||||
|
this.$eventHub.$on(READLIST_DELETED, this.readListDeleted)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCounts)
|
this.$eventHub.$off(COLLECTION_ADDED, this.collectionAdded)
|
||||||
this.$eventHub.$off(READLIST_CHANGED, this.reloadCounts)
|
this.$eventHub.$off(COLLECTION_DELETED, this.collectionDeleted)
|
||||||
|
this.$eventHub.$off(READLIST_ADDED, this.readListAdded)
|
||||||
|
this.$eventHub.$off(READLIST_DELETED, this.readListDeleted)
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
showRecommended(): boolean {
|
showRecommended(): boolean {
|
||||||
|
|
@ -123,15 +128,27 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
reloadCounts() {
|
readListAdded() {
|
||||||
this.loadCounts(this.libraryId)
|
if(this.readListsCount === 0) this.loadReadListCounts(this.libraryId)
|
||||||
},
|
},
|
||||||
async loadCounts(libraryId: string) {
|
readListDeleted() {
|
||||||
|
if(this.readListsCount === 1) this.loadReadListCounts(this.libraryId)
|
||||||
|
},
|
||||||
|
collectionAdded() {
|
||||||
|
if(this.collectionsCount === 0) this.loadCollectionCounts(this.libraryId)
|
||||||
|
},
|
||||||
|
collectionDeleted() {
|
||||||
|
if(this.collectionsCount === 1) this.loadCollectionCounts(this.libraryId)
|
||||||
|
},
|
||||||
|
async loadCollectionCounts(libraryId: string) {
|
||||||
const lib = libraryId !== LIBRARIES_ALL ? [libraryId] : undefined
|
const lib = libraryId !== LIBRARIES_ALL ? [libraryId] : undefined
|
||||||
this.$komgaCollections.getCollections(lib, {size: 0})
|
this.$komgaCollections.getCollections(lib, {size: 0})
|
||||||
.then(v => this.collectionsCount = v.totalElements)
|
.then(v => this.collectionsCount = v.totalElements)
|
||||||
|
},
|
||||||
|
async loadReadListCounts(libraryId: string) {
|
||||||
|
const lib = libraryId !== LIBRARIES_ALL ? [libraryId] : undefined
|
||||||
await this.$komgaReadLists.getReadLists(lib, {size: 0})
|
await this.$komgaReadLists.getReadLists(lib, {size: 0})
|
||||||
.then(v => this.readListsCount = v.totalElements)
|
.then(v => this.readListsCount = v.totalElements)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
117
komga-webui/src/components/Toaster.vue
Normal file
117
komga-webui/src/components/Toaster.vue
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
<template>
|
||||||
|
<v-snackbar
|
||||||
|
v-model="snackbar.show"
|
||||||
|
:color="snackbar.color"
|
||||||
|
bottom
|
||||||
|
multi-line
|
||||||
|
vertical
|
||||||
|
:timeout="snackbar.timeout"
|
||||||
|
>
|
||||||
|
<p>{{ snackbar.text }}</p>
|
||||||
|
<p>{{ snackbar.text2 }}</p>
|
||||||
|
<template v-slot:action="{ attrs }">
|
||||||
|
<v-btn
|
||||||
|
v-if="snackbar.goTo"
|
||||||
|
color="secondary"
|
||||||
|
text
|
||||||
|
v-bind="attrs"
|
||||||
|
@click="snackbar.goTo.click"
|
||||||
|
>
|
||||||
|
{{ snackbar.goTo.text }}
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
|
<v-btn
|
||||||
|
text
|
||||||
|
v-bind="attrs"
|
||||||
|
@click="close"
|
||||||
|
>{{ $t('common.dismiss') }}</v-btn>
|
||||||
|
</template>
|
||||||
|
</v-snackbar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue'
|
||||||
|
import {BOOK_IMPORTED} from "@/types/events";
|
||||||
|
import {convertErrorCodes} from "@/functions/error-codes";
|
||||||
|
import {BookImportSseDto} from "@/types/komga-sse";
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
name: 'Toaster',
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
queue: [] as any[],
|
||||||
|
snackbar: {
|
||||||
|
show: false,
|
||||||
|
text: '',
|
||||||
|
text2: '',
|
||||||
|
color: undefined,
|
||||||
|
timeout: 5000,
|
||||||
|
goTo: {
|
||||||
|
text: '',
|
||||||
|
click: () => {
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.$eventHub.$on(BOOK_IMPORTED, this.bookImported)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.$eventHub.$off(BOOK_IMPORTED, this.bookImported)
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'snackbar.show'(val) {
|
||||||
|
if (!val) {
|
||||||
|
setTimeout(() => this.next(), 1000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
queue(val) {
|
||||||
|
if (val.length > 0) {
|
||||||
|
this.next()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
close() {
|
||||||
|
this.snackbar.show = false
|
||||||
|
},
|
||||||
|
next() {
|
||||||
|
if (this.snackbar.show) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.queue.length > 0) {
|
||||||
|
const snack = this.queue.shift()
|
||||||
|
this.snackbar.text = snack.text
|
||||||
|
this.snackbar.text2 = snack.text2
|
||||||
|
this.snackbar.goTo = snack.goTo
|
||||||
|
this.snackbar.color = snack.color
|
||||||
|
this.snackbar.show = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async bookImported(event: BookImportSseDto) {
|
||||||
|
if (event.success && event.bookId) {
|
||||||
|
const book = await this.$komgaBooks.getBook(event.bookId)
|
||||||
|
this.queue.push({
|
||||||
|
text: this.$t('book_import.notification.import_successful', {book: book.metadata.title}).toString(),
|
||||||
|
text2: this.$t('book_import.notification.source_file', {file: event.sourceFile}).toString(),
|
||||||
|
goTo: {
|
||||||
|
text: this.$t('book_import.notification.go_to_book').toString(),
|
||||||
|
click: () => this.$router.push({name: 'browse-book', params: {bookId: book.id}}),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.queue.push({
|
||||||
|
text: this.$t('book_import.notification.import_failure', {file: event.sourceFile}).toString(),
|
||||||
|
text2: convertErrorCodes(event.message || ''),
|
||||||
|
color: 'error',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -155,7 +155,6 @@ export default Vue.extend({
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.$komgaCollections.patchCollection(collection.id, toUpdate)
|
await this.$komgaCollections.patchCollection(collection.id, toUpdate)
|
||||||
this.$emit('added', collection)
|
|
||||||
this.dialogClose()
|
this.dialogClose()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.showSnack(e.message)
|
this.showSnack(e.message)
|
||||||
|
|
@ -170,7 +169,6 @@ export default Vue.extend({
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const created = await this.$komgaCollections.postCollection(toCreate)
|
const created = await this.$komgaCollections.postCollection(toCreate)
|
||||||
this.$emit('created', created)
|
|
||||||
this.dialogClose()
|
this.dialogClose()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.showSnack(e.message)
|
this.showSnack(e.message)
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,6 @@ export default Vue.extend({
|
||||||
async deleteCollection() {
|
async deleteCollection() {
|
||||||
try {
|
try {
|
||||||
await this.$komgaCollections.deleteCollection(this.collection.id)
|
await this.$komgaCollections.deleteCollection(this.collection.id)
|
||||||
this.$emit('deleted', true)
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.showSnack(e.message)
|
this.showSnack(e.message)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,6 @@ export default Vue.extend({
|
||||||
} as CollectionUpdateDto
|
} as CollectionUpdateDto
|
||||||
|
|
||||||
await this.$komgaCollections.patchCollection(this.collection.id, update)
|
await this.$komgaCollections.patchCollection(this.collection.id, update)
|
||||||
this.$emit('updated', true)
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.showSnack(e.message)
|
this.showSnack(e.message)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -532,7 +532,6 @@ export default Vue.extend({
|
||||||
for (const b of toUpdate) {
|
for (const b of toUpdate) {
|
||||||
try {
|
try {
|
||||||
await this.$komgaBooks.updateMetadata(b.id, metadata)
|
await this.$komgaBooks.updateMetadata(b.id, metadata)
|
||||||
this.$emit('updated', b)
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.showSnack(e.message)
|
this.showSnack(e.message)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -591,7 +591,6 @@ export default Vue.extend({
|
||||||
for (const s of toUpdate) {
|
for (const s of toUpdate) {
|
||||||
try {
|
try {
|
||||||
await this.$komgaSeries.updateMetadata(s.id, metadata)
|
await this.$komgaSeries.updateMetadata(s.id, metadata)
|
||||||
this.$emit('updated', s)
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.showSnack(e.message)
|
this.showSnack(e.message)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,6 @@ export default Vue.extend({
|
||||||
async deleteLibrary() {
|
async deleteLibrary() {
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch('deleteLibrary', this.library)
|
await this.$store.dispatch('deleteLibrary', this.library)
|
||||||
this.$emit('deleted', true)
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.showSnack(e.message)
|
this.showSnack(e.message)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,6 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import FileBrowserDialog from '@/components/dialogs/FileBrowserDialog.vue'
|
import FileBrowserDialog from '@/components/dialogs/FileBrowserDialog.vue'
|
||||||
import {LIBRARY_ADDED, LIBRARY_CHANGED, libraryToEventLibraryChanged} from '@/types/events'
|
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {required} from 'vuelidate/lib/validators'
|
import {required} from 'vuelidate/lib/validators'
|
||||||
|
|
||||||
|
|
@ -435,10 +434,8 @@ export default Vue.extend({
|
||||||
try {
|
try {
|
||||||
if (this.library) {
|
if (this.library) {
|
||||||
await this.$store.dispatch('updateLibrary', {libraryId: this.library.id, library: library})
|
await this.$store.dispatch('updateLibrary', {libraryId: this.library.id, library: library})
|
||||||
this.$eventHub.$emit(LIBRARY_CHANGED, libraryToEventLibraryChanged(this.library))
|
|
||||||
} else {
|
} else {
|
||||||
await this.$store.dispatch('postLibrary', library)
|
await this.$store.dispatch('postLibrary', library)
|
||||||
this.$eventHub.$emit(LIBRARY_ADDED)
|
|
||||||
}
|
}
|
||||||
this.dialogClose()
|
this.dialogClose()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,6 @@ export default Vue.extend({
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.$komgaReadLists.patchReadList(readList.id, toUpdate)
|
await this.$komgaReadLists.patchReadList(readList.id, toUpdate)
|
||||||
this.$emit('added', readList)
|
|
||||||
this.dialogClose()
|
this.dialogClose()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.showSnack(e.message)
|
this.showSnack(e.message)
|
||||||
|
|
@ -165,7 +164,6 @@ export default Vue.extend({
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const created = await this.$komgaReadLists.postReadList(toCreate)
|
const created = await this.$komgaReadLists.postReadList(toCreate)
|
||||||
this.$emit('created', created)
|
|
||||||
this.dialogClose()
|
this.dialogClose()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.showSnack(e.message)
|
this.showSnack(e.message)
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,6 @@ export default Vue.extend({
|
||||||
async delete() {
|
async delete() {
|
||||||
try {
|
try {
|
||||||
await this.$komgaReadLists.deleteReadList(this.readList.id)
|
await this.$komgaReadLists.deleteReadList(this.readList.id)
|
||||||
this.$emit('deleted', true)
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.showSnack(e.message)
|
this.showSnack(e.message)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,6 @@ export default Vue.extend({
|
||||||
} as ReadListUpdateDto
|
} as ReadListUpdateDto
|
||||||
|
|
||||||
await this.$komgaReadLists.patchReadList(this.readList.id, update)
|
await this.$komgaReadLists.patchReadList(this.readList.id, update)
|
||||||
this.$emit('updated', true)
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.showSnack(e.message)
|
this.showSnack(e.message)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {getReadProgress} from '@/functions/book-progress'
|
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 Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {BookDto, ReadProgressUpdateDto} from '@/types/komga-books'
|
import {BookDto, ReadProgressUpdateDto} from '@/types/komga-books'
|
||||||
|
|
||||||
|
|
@ -79,11 +78,9 @@ export default Vue.extend({
|
||||||
async markRead () {
|
async markRead () {
|
||||||
const readProgress = { completed: true } as ReadProgressUpdateDto
|
const readProgress = { completed: true } as ReadProgressUpdateDto
|
||||||
await this.$komgaBooks.updateReadProgress(this.book.id, readProgress)
|
await this.$komgaBooks.updateReadProgress(this.book.id, readProgress)
|
||||||
this.$eventHub.$emit(BOOK_CHANGED, bookToEventBookChanged(this.book))
|
|
||||||
},
|
},
|
||||||
async markUnread () {
|
async markUnread () {
|
||||||
await this.$komgaBooks.deleteReadProgress(this.book.id)
|
await this.$komgaBooks.deleteReadProgress(this.book.id)
|
||||||
this.$eventHub.$emit(BOOK_CHANGED, bookToEventBookChanged(this.book))
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {SERIES_CHANGED, seriesToEventSeriesChanged} from '@/types/events'
|
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {SeriesDto} from "@/types/komga-series";
|
import {SeriesDto} from "@/types/komga-series";
|
||||||
|
|
||||||
|
|
@ -76,11 +75,11 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
async markRead () {
|
async markRead () {
|
||||||
await this.$komgaSeries.markAsRead(this.series.id)
|
await this.$komgaSeries.markAsRead(this.series.id)
|
||||||
this.$eventHub.$emit(SERIES_CHANGED, seriesToEventSeriesChanged(this.series))
|
// this.$eventHub.$emit(SERIES_CHANGED, seriesToEventSeriesChanged(this.series))
|
||||||
},
|
},
|
||||||
async markUnread () {
|
async markUnread () {
|
||||||
await this.$komgaSeries.markAsUnread(this.series.id)
|
await this.$komgaSeries.markAsUnread(this.series.id)
|
||||||
this.$eventHub.$emit(SERIES_CHANGED, seriesToEventSeriesChanged(this.series))
|
// this.$eventHub.$emit(SERIES_CHANGED, seriesToEventSeriesChanged(this.series))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,12 @@
|
||||||
"field_import_path": "Import from folder",
|
"field_import_path": "Import from folder",
|
||||||
"info_part1": "This screen lets you import files that are outside your existing libraries. You can only import files into existing Series, in which case Komga will move or copy the files into the directory of the chosen Series.",
|
"info_part1": "This screen lets you import files that are outside your existing libraries. You can only import files into existing Series, in which case Komga will move or copy the files into the directory of the chosen Series.",
|
||||||
"info_part2": "If you choose a number for a book, and a book already exists with that number, then you will be able to compare the 2 books. If you decide to import the book, Komga will upgrade the existing book with the new one, effectively replacing the old file with the new.",
|
"info_part2": "If you choose a number for a book, and a book already exists with that number, then you will be able to compare the 2 books. If you decide to import the book, Komga will upgrade the existing book with the new one, effectively replacing the old file with the new.",
|
||||||
|
"notification": {
|
||||||
|
"go_to_book": "Go to book",
|
||||||
|
"import_failure": "Failed to import book: {file}",
|
||||||
|
"import_successful": "Book imported successfully: {book}",
|
||||||
|
"source_file": "Source file: {file}"
|
||||||
|
},
|
||||||
"row": {
|
"row": {
|
||||||
"error_analyze_first": "Book needs to be analyzed first",
|
"error_analyze_first": "Book needs to be analyzed first",
|
||||||
"error_choose_series": "Choose a series",
|
"error_choose_series": "Choose a series",
|
||||||
|
|
@ -159,6 +165,7 @@
|
||||||
"collections": "Collections",
|
"collections": "Collections",
|
||||||
"create": "Create",
|
"create": "Create",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
|
"dismiss": "Dismiss",
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"filter_no_matches": "The active filter has no matches",
|
"filter_no_matches": "The active filter has no matches",
|
||||||
|
|
@ -177,12 +184,13 @@
|
||||||
"read": "Read",
|
"read": "Read",
|
||||||
"readlists": "Read Lists",
|
"readlists": "Read Lists",
|
||||||
"required": "Required",
|
"required": "Required",
|
||||||
|
"reset_filters": "Reset filters",
|
||||||
"roles": "Roles",
|
"roles": "Roles",
|
||||||
"series": "Series",
|
"series": "Series",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"use_filter_panel_to_change_filter": "Use the filter panel to change the active filter",
|
"use_filter_panel_to_change_filter": "Use the filter panel to change the active filter",
|
||||||
"year": "year",
|
"year": "year",
|
||||||
"reset_filters": "Reset filters"
|
"pending_tasks": "No pending tasks | 1 pending task | {count} pending tasks"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"keep_reading": "Keep Reading",
|
"keep_reading": "Keep Reading",
|
||||||
|
|
@ -469,7 +477,12 @@
|
||||||
"ERR_1014": "No match for book number within series",
|
"ERR_1014": "No match for book number within series",
|
||||||
"ERR_1015": "Error while deserializing ComicRack ReadingList",
|
"ERR_1015": "Error while deserializing ComicRack ReadingList",
|
||||||
"ERR_1016": "Directory not accessible or not a directory",
|
"ERR_1016": "Directory not accessible or not a directory",
|
||||||
"ERR_1017": "Cannot scan folder that is part of an existing library"
|
"ERR_1017": "Cannot scan folder that is part of an existing library",
|
||||||
|
"ERR_1018": "File not found",
|
||||||
|
"ERR_1019": "Cannot import file that is part of an existing library",
|
||||||
|
"ERR_1020": "Book to upgrade does not belong to provided series",
|
||||||
|
"ERR_1021": "Destination file already exists",
|
||||||
|
"ERR_1022": "Newly imported book could not be scanned"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"age_rating": "age rating",
|
"age_rating": "age rating",
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,16 @@ import komgaReferential from './plugins/komga-referential.plugin'
|
||||||
import komgaSeries from './plugins/komga-series.plugin'
|
import komgaSeries from './plugins/komga-series.plugin'
|
||||||
import komgaUsers from './plugins/komga-users.plugin'
|
import komgaUsers from './plugins/komga-users.plugin'
|
||||||
import komgaTransientBooks from './plugins/komga-transientbooks.plugin'
|
import komgaTransientBooks from './plugins/komga-transientbooks.plugin'
|
||||||
|
import komgaSse from './plugins/komga-sse.plugin'
|
||||||
import vuetify from './plugins/vuetify'
|
import vuetify from './plugins/vuetify'
|
||||||
import './public-path'
|
import './public-path'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import store from './store'
|
import store from './store'
|
||||||
import i18n from './i18n'
|
import i18n from './i18n'
|
||||||
|
|
||||||
|
Vue.prototype.$_ = _
|
||||||
|
Vue.prototype.$eventHub = new Vue()
|
||||||
|
|
||||||
Vue.use(Vuelidate)
|
Vue.use(Vuelidate)
|
||||||
Vue.use(lineClamp)
|
Vue.use(lineClamp)
|
||||||
Vue.use(VueCookies)
|
Vue.use(VueCookies)
|
||||||
|
|
@ -39,10 +43,9 @@ Vue.use(komgaClaim, {http: Vue.prototype.$http})
|
||||||
Vue.use(komgaTransientBooks, {http: Vue.prototype.$http})
|
Vue.use(komgaTransientBooks, {http: Vue.prototype.$http})
|
||||||
Vue.use(komgaUsers, {store: store, http: Vue.prototype.$http})
|
Vue.use(komgaUsers, {store: store, http: Vue.prototype.$http})
|
||||||
Vue.use(komgaLibraries, {store: store, http: Vue.prototype.$http})
|
Vue.use(komgaLibraries, {store: store, http: Vue.prototype.$http})
|
||||||
|
Vue.use(komgaSse, {eventHub: Vue.prototype.$eventHub, store: store})
|
||||||
Vue.use(actuator, {http: Vue.prototype.$http})
|
Vue.use(actuator, {http: Vue.prototype.$http})
|
||||||
|
|
||||||
Vue.prototype.$_ = _
|
|
||||||
Vue.prototype.$eventHub = new Vue()
|
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import KomgaLibrariesService from '@/services/komga-libraries.service'
|
import KomgaLibrariesService from '@/services/komga-libraries.service'
|
||||||
import { AxiosInstance } from 'axios'
|
import {AxiosInstance} from 'axios'
|
||||||
import _Vue from 'vue'
|
import _Vue from 'vue'
|
||||||
import { Module } from 'vuex/types'
|
import {Module} from 'vuex/types'
|
||||||
|
|
||||||
let service: KomgaLibrariesService
|
let service: KomgaLibrariesService
|
||||||
|
|
||||||
|
|
@ -25,15 +25,12 @@ const vuexModule: Module<any, any> = {
|
||||||
},
|
},
|
||||||
async postLibrary ({ dispatch }, library) {
|
async postLibrary ({ dispatch }, library) {
|
||||||
await service.postLibrary(library)
|
await service.postLibrary(library)
|
||||||
await dispatch('getLibraries')
|
|
||||||
},
|
},
|
||||||
async updateLibrary ({ dispatch }, { libraryId, library }) {
|
async updateLibrary ({ dispatch }, { libraryId, library }) {
|
||||||
await service.updateLibrary(libraryId, library)
|
await service.updateLibrary(libraryId, library)
|
||||||
await dispatch('getLibraries')
|
|
||||||
},
|
},
|
||||||
async deleteLibrary ({ dispatch }, library) {
|
async deleteLibrary ({ dispatch }, library) {
|
||||||
await service.deleteLibrary(library)
|
await service.deleteLibrary(library)
|
||||||
await dispatch('getLibraries')
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
komga-webui/src/plugins/komga-sse.plugin.ts
Normal file
31
komga-webui/src/plugins/komga-sse.plugin.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
import _Vue from 'vue'
|
||||||
|
import KomgaSseService from "@/services/komga-sse.service"
|
||||||
|
import {Module} from "vuex";
|
||||||
|
|
||||||
|
const vuexModule: Module<any, any> = {
|
||||||
|
state: {
|
||||||
|
taskCount: 0,
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
setTaskCount (state, val) {
|
||||||
|
state.taskCount = val
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
install(
|
||||||
|
Vue: typeof _Vue,
|
||||||
|
{eventHub, store}: { eventHub: _Vue, store: any },
|
||||||
|
) {
|
||||||
|
store.registerModule('komgaSse', vuexModule)
|
||||||
|
|
||||||
|
Vue.prototype.$komgaSse = new KomgaSseService(eventHub, store)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'vue/types/vue' {
|
||||||
|
interface Vue {
|
||||||
|
$komgaSse: KomgaSseService;
|
||||||
|
}
|
||||||
|
}
|
||||||
99
komga-webui/src/services/komga-sse.service.ts
Normal file
99
komga-webui/src/services/komga-sse.service.ts
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
import urls from '@/functions/urls'
|
||||||
|
import {
|
||||||
|
BOOK_ADDED,
|
||||||
|
BOOK_CHANGED,
|
||||||
|
BOOK_DELETED,
|
||||||
|
BOOK_IMPORTED,
|
||||||
|
COLLECTION_ADDED,
|
||||||
|
COLLECTION_CHANGED,
|
||||||
|
COLLECTION_DELETED,
|
||||||
|
LIBRARY_ADDED,
|
||||||
|
LIBRARY_CHANGED,
|
||||||
|
LIBRARY_DELETED,
|
||||||
|
READLIST_ADDED,
|
||||||
|
READLIST_CHANGED,
|
||||||
|
READLIST_DELETED,
|
||||||
|
READPROGRESS_CHANGED,
|
||||||
|
READPROGRESS_DELETED,
|
||||||
|
SERIES_ADDED,
|
||||||
|
SERIES_CHANGED,
|
||||||
|
SERIES_DELETED,
|
||||||
|
THUMBNAILBOOK_ADDED,
|
||||||
|
THUMBNAILSERIES_ADDED,
|
||||||
|
} from "@/types/events";
|
||||||
|
import Vue from "vue";
|
||||||
|
import {TaskQueueSseDto} from "@/types/komga-sse";
|
||||||
|
|
||||||
|
const API_SSE = '/sse/v1/events'
|
||||||
|
|
||||||
|
export default class KomgaSseService {
|
||||||
|
private eventSource: EventSource | undefined
|
||||||
|
private eventHub: Vue
|
||||||
|
private store: any
|
||||||
|
|
||||||
|
constructor(eventHub: Vue, store: any) {
|
||||||
|
this.eventHub = eventHub
|
||||||
|
this.store = store
|
||||||
|
|
||||||
|
this.eventHub.$watch(
|
||||||
|
() => this.store.getters.authenticated,
|
||||||
|
(val) => {
|
||||||
|
if (val) this.connect()
|
||||||
|
else this.disconnect()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
this.eventSource = new EventSource(urls.originNoSlash + API_SSE, {withCredentials: true})
|
||||||
|
|
||||||
|
// Libraries
|
||||||
|
this.eventSource.addEventListener('LibraryAdded', (event: any) => this.emit(LIBRARY_ADDED, event))
|
||||||
|
this.eventSource.addEventListener('LibraryChanged', (event: any) => this.emit(LIBRARY_CHANGED, event))
|
||||||
|
this.eventSource.addEventListener('LibraryDeleted', (event: any) => this.emit(LIBRARY_DELETED, event))
|
||||||
|
|
||||||
|
// Series
|
||||||
|
this.eventSource.addEventListener('SeriesAdded', (event: any) => this.emit(SERIES_ADDED, event))
|
||||||
|
this.eventSource.addEventListener('SeriesChanged', (event: any) => this.emit(SERIES_CHANGED, event))
|
||||||
|
this.eventSource.addEventListener('SeriesDeleted', (event: any) => this.emit(SERIES_DELETED, event))
|
||||||
|
|
||||||
|
// Books
|
||||||
|
this.eventSource.addEventListener('BookAdded', (event: any) => this.emit(BOOK_ADDED, event))
|
||||||
|
this.eventSource.addEventListener('BookChanged', (event: any) => this.emit(BOOK_CHANGED, event))
|
||||||
|
this.eventSource.addEventListener('BookDeleted', (event: any) => this.emit(BOOK_DELETED, event))
|
||||||
|
|
||||||
|
this.eventSource.addEventListener('BookImported', (event: any) => this.emit(BOOK_IMPORTED, event))
|
||||||
|
|
||||||
|
// Collections
|
||||||
|
this.eventSource.addEventListener('CollectionAdded', (event: any) => this.emit(COLLECTION_ADDED, event))
|
||||||
|
this.eventSource.addEventListener('CollectionChanged', (event: any) => this.emit(COLLECTION_CHANGED, event))
|
||||||
|
this.eventSource.addEventListener('CollectionDeleted', (event: any) => this.emit(COLLECTION_DELETED, event))
|
||||||
|
|
||||||
|
// Read Lists
|
||||||
|
this.eventSource.addEventListener('ReadListAdded', (event: any) => this.emit(READLIST_ADDED, event))
|
||||||
|
this.eventSource.addEventListener('ReadListChanged', (event: any) => this.emit(READLIST_CHANGED, event))
|
||||||
|
this.eventSource.addEventListener('ReadListDeleted', (event: any) => this.emit(READLIST_DELETED, event))
|
||||||
|
|
||||||
|
// Read Progress
|
||||||
|
this.eventSource.addEventListener('ReadProgressChanged', (event: any) => this.emit(READPROGRESS_CHANGED, event))
|
||||||
|
this.eventSource.addEventListener('ReadProgressDeleted', (event: any) => this.emit(READPROGRESS_DELETED, event))
|
||||||
|
|
||||||
|
// Thumbnails
|
||||||
|
this.eventSource.addEventListener('ThumbnailBookAdded', (event: any) => this.emit(THUMBNAILBOOK_ADDED, event))
|
||||||
|
this.eventSource.addEventListener('ThumbnailSeriesAdded', (event: any) => this.emit(THUMBNAILSERIES_ADDED, event))
|
||||||
|
|
||||||
|
this.eventSource.addEventListener('TaskQueueStatus', (event: any) => this.updateTaskCount(event))
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
this.eventSource?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
private emit(name: string, event: any) {
|
||||||
|
this.eventHub.$emit(name, JSON.parse(event.data))
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateTaskCount(event: any) {
|
||||||
|
const data = JSON.parse(event.data) as TaskQueueSseDto
|
||||||
|
this.store.commit('setTaskCount', data.count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,7 +23,7 @@ export enum ReadStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function replaceCompositeReadStatus(list: string[]): string[] {
|
export function replaceCompositeReadStatus(list: string[]): string[] {
|
||||||
if(list.includes(ReadStatus.UNREAD_AND_IN_PROGRESS)){
|
if(list?.includes(ReadStatus.UNREAD_AND_IN_PROGRESS)){
|
||||||
return [...without(list, ReadStatus.UNREAD_AND_IN_PROGRESS), ReadStatus.UNREAD, ReadStatus.IN_PROGRESS]
|
return [...without(list, ReadStatus.UNREAD_AND_IN_PROGRESS), ReadStatus.UNREAD, ReadStatus.IN_PROGRESS]
|
||||||
}
|
}
|
||||||
else return list
|
else return list
|
||||||
|
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
interface EventBookChanged {
|
|
||||||
id: string,
|
|
||||||
seriesId: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EventSeriesChanged {
|
|
||||||
id: string,
|
|
||||||
libraryId: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EventCollectionChanged {
|
|
||||||
id: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EventCollectionDeleted {
|
|
||||||
id: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EventReadListChanged {
|
|
||||||
id: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EventReadListDeleted {
|
|
||||||
id: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EventLibraryAdded {
|
|
||||||
id: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EventLibraryChanged {
|
|
||||||
id: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EventLibraryDeleted {
|
|
||||||
id: string
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +1,26 @@
|
||||||
import { BookDto } from '@/types/komga-books'
|
|
||||||
import {SeriesDto} from "@/types/komga-series";
|
|
||||||
|
|
||||||
export const BOOK_CHANGED = 'book-changed'
|
|
||||||
export const SERIES_CHANGED = 'series-changed'
|
|
||||||
export const COLLECTION_DELETED = 'collection-deleted'
|
|
||||||
export const COLLECTION_CHANGED = 'collection-changed'
|
|
||||||
export const READLIST_DELETED = 'readlist-deleted'
|
|
||||||
export const READLIST_CHANGED = 'readlist-changed'
|
|
||||||
export const LIBRARY_ADDED = 'library-added'
|
export const LIBRARY_ADDED = 'library-added'
|
||||||
export const LIBRARY_CHANGED = 'library-changed'
|
export const LIBRARY_CHANGED = 'library-changed'
|
||||||
export const LIBRARY_DELETED = 'library-deleted'
|
export const LIBRARY_DELETED = 'library-deleted'
|
||||||
|
|
||||||
export function bookToEventBookChanged (book: BookDto): EventBookChanged {
|
export const BOOK_ADDED = 'book-added'
|
||||||
return {
|
export const BOOK_CHANGED = 'book-changed'
|
||||||
id: book.id,
|
export const BOOK_DELETED = 'book-deleted'
|
||||||
seriesId: book.seriesId,
|
export const BOOK_IMPORTED = 'book-imported'
|
||||||
} as EventBookChanged
|
|
||||||
}
|
|
||||||
|
|
||||||
export function seriesToEventSeriesChanged (series: SeriesDto): EventSeriesChanged {
|
export const SERIES_ADDED = 'series-added'
|
||||||
return {
|
export const SERIES_CHANGED = 'series-changed'
|
||||||
id: series.id,
|
export const SERIES_DELETED = 'series-deleted'
|
||||||
libraryId: series.libraryId,
|
|
||||||
} as EventSeriesChanged
|
|
||||||
}
|
|
||||||
|
|
||||||
export function collectionToEventCollectionChanged (collection: CollectionDto): EventCollectionChanged {
|
export const COLLECTION_ADDED = 'collection-added'
|
||||||
return {
|
export const COLLECTION_CHANGED = 'collection-changed'
|
||||||
id: collection.id,
|
export const COLLECTION_DELETED = 'collection-deleted'
|
||||||
} as EventCollectionChanged
|
|
||||||
}
|
|
||||||
|
|
||||||
export function collectionToEventCollectionDeleted (collection: CollectionDto): EventCollectionDeleted {
|
export const READLIST_ADDED = 'readlist-added'
|
||||||
return {
|
export const READLIST_CHANGED = 'readlist-changed'
|
||||||
id: collection.id,
|
export const READLIST_DELETED = 'readlist-deleted'
|
||||||
} as EventCollectionDeleted
|
|
||||||
}
|
|
||||||
|
|
||||||
export function readListToEventReadListChanged (readList: ReadListDto): EventReadListChanged {
|
export const READPROGRESS_CHANGED = 'readprogress-changed'
|
||||||
return {
|
export const READPROGRESS_DELETED = 'readprogress-deleted'
|
||||||
id: readList.id,
|
|
||||||
} as EventReadListChanged
|
|
||||||
}
|
|
||||||
|
|
||||||
export function readListToEventReadListDeleted (readList: ReadListDto): EventReadListDeleted {
|
export const THUMBNAILBOOK_ADDED = 'thumbnailbook-added'
|
||||||
return {
|
export const THUMBNAILSERIES_ADDED = 'thumbnailbook-added'
|
||||||
id: readList.id,
|
|
||||||
} as EventReadListDeleted
|
|
||||||
}
|
|
||||||
|
|
||||||
export function libraryToEventLibraryAdded (library: LibraryDto): EventLibraryAdded {
|
|
||||||
return {
|
|
||||||
id: library.id,
|
|
||||||
} as EventLibraryAdded
|
|
||||||
}
|
|
||||||
|
|
||||||
export function libraryToEventLibraryChanged (library: LibraryDto): EventLibraryChanged {
|
|
||||||
return {
|
|
||||||
id: library.id,
|
|
||||||
} as EventLibraryChanged
|
|
||||||
}
|
|
||||||
|
|
||||||
export function libraryToEventLibraryDeleted (library: LibraryDto): EventLibraryDeleted {
|
|
||||||
return {
|
|
||||||
id: library.id,
|
|
||||||
} as EventLibraryDeleted
|
|
||||||
}
|
|
||||||
|
|
|
||||||
49
komga-webui/src/types/komga-sse.ts
Normal file
49
komga-webui/src/types/komga-sse.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
export interface LibrarySseDto {
|
||||||
|
libraryId: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SeriesSseDto {
|
||||||
|
seriesId: string,
|
||||||
|
libraryId: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BookSseDto {
|
||||||
|
bookId: string,
|
||||||
|
seriesId: string,
|
||||||
|
libraryId: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CollectionSseDto {
|
||||||
|
collectionId: string,
|
||||||
|
seriesIds: string[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReadListSseDto {
|
||||||
|
readListId: string,
|
||||||
|
bookIds: string[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReadProgressSseDto {
|
||||||
|
bookId: string,
|
||||||
|
userId: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ThumbnailBookSseDto {
|
||||||
|
bookId: string,
|
||||||
|
seriesId: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ThumbnailSeriesSseDto {
|
||||||
|
seriesId: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskQueueSseDto {
|
||||||
|
count: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BookImportSseDto {
|
||||||
|
bookId?: string,
|
||||||
|
sourceFile: string,
|
||||||
|
success: boolean,
|
||||||
|
message?: string,
|
||||||
|
}
|
||||||
|
|
@ -322,7 +322,16 @@ import {getReadProgress, getReadProgressPercentage} from '@/functions/book-progr
|
||||||
import {getBookTitleCompact} from '@/functions/book-title'
|
import {getBookTitleCompact} from '@/functions/book-title'
|
||||||
import {bookFileUrl, bookThumbnailUrl} from '@/functions/urls'
|
import {bookFileUrl, bookThumbnailUrl} from '@/functions/urls'
|
||||||
import {ReadStatus} from '@/types/enum-books'
|
import {ReadStatus} from '@/types/enum-books'
|
||||||
import {BOOK_CHANGED, LIBRARY_DELETED} from '@/types/events'
|
import {
|
||||||
|
BOOK_CHANGED,
|
||||||
|
BOOK_DELETED,
|
||||||
|
LIBRARY_DELETED,
|
||||||
|
READLIST_ADDED,
|
||||||
|
READLIST_CHANGED,
|
||||||
|
READLIST_DELETED,
|
||||||
|
READPROGRESS_CHANGED,
|
||||||
|
READPROGRESS_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 {BookDto, BookFormat} from '@/types/komga-books'
|
||||||
|
|
@ -333,6 +342,7 @@ import VueHorizontal from "vue-horizontal";
|
||||||
import {authorRoles} from "@/types/author-roles";
|
import {authorRoles} from "@/types/author-roles";
|
||||||
import {convertErrorCodes} from "@/functions/error-codes";
|
import {convertErrorCodes} from "@/functions/error-codes";
|
||||||
import RtlIcon from "@/components/RtlIcon.vue";
|
import RtlIcon from "@/components/RtlIcon.vue";
|
||||||
|
import {BookSseDto, LibrarySseDto, ReadListSseDto, ReadProgressSseDto} from "@/types/komga-sse";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'BrowseBook',
|
name: 'BrowseBook',
|
||||||
|
|
@ -351,12 +361,24 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
this.loadBook(this.bookId)
|
this.loadBook(this.bookId)
|
||||||
this.$eventHub.$on(BOOK_CHANGED, this.reloadBook)
|
this.$eventHub.$on(BOOK_CHANGED, this.bookChanged)
|
||||||
|
this.$eventHub.$on(BOOK_DELETED, this.bookDeleted)
|
||||||
|
this.$eventHub.$on(READPROGRESS_CHANGED, this.readProgressChanged)
|
||||||
|
this.$eventHub.$on(READPROGRESS_DELETED, this.readProgressChanged)
|
||||||
this.$eventHub.$on(LIBRARY_DELETED, this.libraryDeleted)
|
this.$eventHub.$on(LIBRARY_DELETED, this.libraryDeleted)
|
||||||
|
this.$eventHub.$on(READLIST_ADDED, this.readListChanged)
|
||||||
|
this.$eventHub.$on(READLIST_CHANGED, this.readListChanged)
|
||||||
|
this.$eventHub.$on(READLIST_DELETED, this.readListChanged)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.$eventHub.$off(BOOK_CHANGED, this.reloadBook)
|
this.$eventHub.$off(BOOK_CHANGED, this.bookChanged)
|
||||||
|
this.$eventHub.$off(BOOK_DELETED, this.bookDeleted)
|
||||||
|
this.$eventHub.$off(READPROGRESS_CHANGED, this.readProgressChanged)
|
||||||
|
this.$eventHub.$off(READPROGRESS_DELETED, this.readProgressChanged)
|
||||||
this.$eventHub.$off(LIBRARY_DELETED, this.libraryDeleted)
|
this.$eventHub.$off(LIBRARY_DELETED, this.libraryDeleted)
|
||||||
|
this.$eventHub.$off(READLIST_ADDED, this.readListChanged)
|
||||||
|
this.$eventHub.$off(READLIST_CHANGED, this.readListChanged)
|
||||||
|
this.$eventHub.$off(READLIST_DELETED, this.readListChanged)
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
bookId: {
|
bookId: {
|
||||||
|
|
@ -434,13 +456,27 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
libraryDeleted(event: EventLibraryDeleted) {
|
libraryDeleted(event: LibrarySseDto) {
|
||||||
if (event.id === this.book.libraryId) {
|
if (event.libraryId === this.book.libraryId) {
|
||||||
this.$router.push({name: 'home'})
|
this.$router.push({name: 'home'})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
reloadBook(event: EventBookChanged) {
|
readListChanged(event: ReadListSseDto) {
|
||||||
if (event.id === this.bookId) this.loadBook(this.bookId)
|
if(event.bookIds.includes(this.bookId) || this.readLists.map(x => x.id).includes(event.readListId)){
|
||||||
|
this.$komgaBooks.getReadLists(this.bookId)
|
||||||
|
.then(v => this.readLists = v)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
bookChanged(event: BookSseDto) {
|
||||||
|
if (event.bookId === this.bookId) this.loadBook(this.bookId)
|
||||||
|
},
|
||||||
|
bookDeleted(event: BookSseDto) {
|
||||||
|
if (event.bookId === this.bookId){
|
||||||
|
this.$router.push({name:'browse-series', params: {seriesId: this.series.id }})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
readProgressChanged(event: ReadProgressSseDto){
|
||||||
|
if (event.bookId === this.bookId) this.loadBook(this.bookId)
|
||||||
},
|
},
|
||||||
async loadBook(bookId: string) {
|
async loadBook(bookId: string) {
|
||||||
this.book = await this.$komgaBooks.getBook(bookId)
|
this.book = await this.$komgaBooks.getBook(bookId)
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@
|
||||||
import CollectionActionsMenu from '@/components/menus/CollectionActionsMenu.vue'
|
import CollectionActionsMenu from '@/components/menus/CollectionActionsMenu.vue'
|
||||||
import ItemBrowser from '@/components/ItemBrowser.vue'
|
import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||||
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
|
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
|
||||||
import {COLLECTION_CHANGED, COLLECTION_DELETED, SERIES_CHANGED} from '@/types/events'
|
import {COLLECTION_CHANGED, COLLECTION_DELETED, SERIES_CHANGED, SERIES_DELETED} from '@/types/events'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import SeriesMultiSelectBar from '@/components/bars/SeriesMultiSelectBar.vue'
|
import SeriesMultiSelectBar from '@/components/bars/SeriesMultiSelectBar.vue'
|
||||||
import {LIBRARIES_ALL} from '@/types/library'
|
import {LIBRARIES_ALL} from '@/types/library'
|
||||||
|
|
@ -130,6 +130,7 @@ import {parseQueryParam} from '@/functions/query-params'
|
||||||
import {SeriesDto} from "@/types/komga-series";
|
import {SeriesDto} from "@/types/komga-series";
|
||||||
import {authorRoles} from "@/types/author-roles";
|
import {authorRoles} from "@/types/author-roles";
|
||||||
import {AuthorDto} from "@/types/komga-books";
|
import {AuthorDto} from "@/types/komga-books";
|
||||||
|
import {CollectionSseDto, SeriesSseDto} from "@/types/komga-sse";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'BrowseCollection',
|
name: 'BrowseCollection',
|
||||||
|
|
@ -186,13 +187,15 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$eventHub.$on(COLLECTION_CHANGED, this.collectionChanged)
|
this.$eventHub.$on(COLLECTION_CHANGED, this.collectionChanged)
|
||||||
this.$eventHub.$on(COLLECTION_DELETED, this.afterDelete)
|
this.$eventHub.$on(COLLECTION_DELETED, this.collectionDeleted)
|
||||||
this.$eventHub.$on(SERIES_CHANGED, this.reloadSeries)
|
this.$eventHub.$on(SERIES_CHANGED, this.seriesChanged)
|
||||||
|
this.$eventHub.$on(SERIES_DELETED, this.seriesChanged)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.$eventHub.$off(COLLECTION_CHANGED, this.collectionChanged)
|
this.$eventHub.$off(COLLECTION_CHANGED, this.collectionChanged)
|
||||||
this.$eventHub.$off(COLLECTION_DELETED, this.afterDelete)
|
this.$eventHub.$off(COLLECTION_DELETED, this.collectionDeleted)
|
||||||
this.$eventHub.$off(SERIES_CHANGED, this.reloadSeries)
|
this.$eventHub.$off(SERIES_CHANGED, this.seriesChanged)
|
||||||
|
this.$eventHub.$off(SERIES_DELETED, this.seriesChanged)
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
await this.resetParams(this.$route, this.collectionId)
|
await this.resetParams(this.$route, this.collectionId)
|
||||||
|
|
@ -345,11 +348,16 @@ export default Vue.extend({
|
||||||
unsetWatches() {
|
unsetWatches() {
|
||||||
this.filterUnwatch()
|
this.filterUnwatch()
|
||||||
},
|
},
|
||||||
collectionChanged(event: EventCollectionChanged) {
|
collectionChanged(event: CollectionSseDto) {
|
||||||
if (event.id === this.collectionId) {
|
if (event.collectionId === this.collectionId) {
|
||||||
this.loadCollection(this.collectionId)
|
this.loadCollection(this.collectionId)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
collectionDeleted(event: CollectionSseDto) {
|
||||||
|
if(event.collectionId === this.collectionId) {
|
||||||
|
this.$router.push({name: 'browse-collections', params: {libraryId: LIBRARIES_ALL}})
|
||||||
|
}
|
||||||
|
},
|
||||||
updateRouteAndReload() {
|
updateRouteAndReload() {
|
||||||
this.unsetWatches()
|
this.unsetWatches()
|
||||||
|
|
||||||
|
|
@ -431,11 +439,8 @@ export default Vue.extend({
|
||||||
editCollection() {
|
editCollection() {
|
||||||
this.$store.dispatch('dialogEditCollection', this.collection)
|
this.$store.dispatch('dialogEditCollection', this.collection)
|
||||||
},
|
},
|
||||||
afterDelete() {
|
seriesChanged(event: SeriesSseDto) {
|
||||||
this.$router.push({name: 'browse-collections', params: {libraryId: LIBRARIES_ALL}})
|
if (this.series.some(s => s.id === event.seriesId)) this.loadCollection(this.collectionId)
|
||||||
},
|
|
||||||
reloadSeries(event: EventSeriesChanged) {
|
|
||||||
if (this.series.some(s => s.id === event.id)) this.loadCollection(this.collectionId)
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -54,10 +54,11 @@ import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||||
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
||||||
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
||||||
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
||||||
import {COLLECTION_CHANGED, COLLECTION_DELETED, LIBRARY_CHANGED} from '@/types/events'
|
import {COLLECTION_ADDED, COLLECTION_CHANGED, COLLECTION_DELETED, LIBRARY_CHANGED} from '@/types/events'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {Location} from 'vue-router'
|
import {Location} from 'vue-router'
|
||||||
import {LIBRARIES_ALL, LIBRARY_ROUTE} from '@/types/library'
|
import {LIBRARIES_ALL, LIBRARY_ROUTE} from '@/types/library'
|
||||||
|
import {LibrarySseDto} from "@/types/komga-sse";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'BrowseCollections',
|
name: 'BrowseCollections',
|
||||||
|
|
@ -87,11 +88,13 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
this.$eventHub.$on(COLLECTION_ADDED, this.reloadCollections)
|
||||||
this.$eventHub.$on(COLLECTION_CHANGED, this.reloadCollections)
|
this.$eventHub.$on(COLLECTION_CHANGED, this.reloadCollections)
|
||||||
this.$eventHub.$on(COLLECTION_DELETED, this.reloadCollections)
|
this.$eventHub.$on(COLLECTION_DELETED, this.reloadCollections)
|
||||||
this.$eventHub.$on(LIBRARY_CHANGED, this.reloadLibrary)
|
this.$eventHub.$on(LIBRARY_CHANGED, this.reloadLibrary)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
|
this.$eventHub.$off(COLLECTION_ADDED, this.reloadCollections)
|
||||||
this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCollections)
|
this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCollections)
|
||||||
this.$eventHub.$off(COLLECTION_DELETED, this.reloadCollections)
|
this.$eventHub.$off(COLLECTION_DELETED, this.reloadCollections)
|
||||||
this.$eventHub.$off(LIBRARY_CHANGED, this.reloadLibrary)
|
this.$eventHub.$off(LIBRARY_CHANGED, this.reloadLibrary)
|
||||||
|
|
@ -179,8 +182,8 @@ export default Vue.extend({
|
||||||
reloadCollections() {
|
reloadCollections() {
|
||||||
this.loadLibrary(this.libraryId)
|
this.loadLibrary(this.libraryId)
|
||||||
},
|
},
|
||||||
reloadLibrary(event: EventLibraryChanged) {
|
reloadLibrary(event: LibrarySseDto) {
|
||||||
if (event.id === this.libraryId) {
|
if (event.libraryId === this.libraryId) {
|
||||||
this.loadLibrary(this.libraryId)
|
this.loadLibrary(this.libraryId)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
||||||
import {parseQueryParam, parseQuerySort} from '@/functions/query-params'
|
import {parseQueryParam, parseQuerySort} from '@/functions/query-params'
|
||||||
import {ReadStatus, replaceCompositeReadStatus} from '@/types/enum-books'
|
import {ReadStatus, replaceCompositeReadStatus} from '@/types/enum-books'
|
||||||
import {SeriesStatus, SeriesStatusKeyValue} from '@/types/enum-series'
|
import {SeriesStatus, SeriesStatusKeyValue} from '@/types/enum-series'
|
||||||
import {LIBRARY_CHANGED, LIBRARY_DELETED, SERIES_CHANGED} from '@/types/events'
|
import {LIBRARY_CHANGED, LIBRARY_DELETED, SERIES_ADDED, SERIES_CHANGED, SERIES_DELETED} from '@/types/events'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {Location} from 'vue-router'
|
import {Location} from 'vue-router'
|
||||||
import {LIBRARIES_ALL, LIBRARY_ROUTE} from '@/types/library'
|
import {LIBRARIES_ALL, LIBRARY_ROUTE} from '@/types/library'
|
||||||
|
|
@ -124,6 +124,7 @@ import {mergeFilterParams, sortOrFilterActive, toNameValue} from '@/functions/fi
|
||||||
import {SeriesDto} from "@/types/komga-series";
|
import {SeriesDto} from "@/types/komga-series";
|
||||||
import {AuthorDto} from "@/types/komga-books";
|
import {AuthorDto} from "@/types/komga-books";
|
||||||
import {authorRoles} from "@/types/author-roles";
|
import {authorRoles} from "@/types/author-roles";
|
||||||
|
import {LibrarySseDto, SeriesSseDto} from "@/types/komga-sse";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'BrowseLibraries',
|
name: 'BrowseLibraries',
|
||||||
|
|
@ -184,14 +185,18 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$eventHub.$on(SERIES_CHANGED, this.reloadSeries)
|
this.$eventHub.$on(SERIES_ADDED, this.seriesChanged)
|
||||||
|
this.$eventHub.$on(SERIES_CHANGED, this.seriesChanged)
|
||||||
|
this.$eventHub.$on(SERIES_DELETED, this.seriesChanged)
|
||||||
this.$eventHub.$on(LIBRARY_DELETED, this.libraryDeleted)
|
this.$eventHub.$on(LIBRARY_DELETED, this.libraryDeleted)
|
||||||
this.$eventHub.$on(LIBRARY_CHANGED, this.reloadLibrary)
|
this.$eventHub.$on(LIBRARY_CHANGED, this.libraryChanged)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.$eventHub.$off(SERIES_CHANGED, this.reloadSeries)
|
this.$eventHub.$off(SERIES_ADDED, this.seriesChanged)
|
||||||
|
this.$eventHub.$off(SERIES_CHANGED, this.seriesChanged)
|
||||||
|
this.$eventHub.$off(SERIES_DELETED, this.seriesChanged)
|
||||||
this.$eventHub.$off(LIBRARY_DELETED, this.libraryDeleted)
|
this.$eventHub.$off(LIBRARY_DELETED, this.libraryDeleted)
|
||||||
this.$eventHub.$off(LIBRARY_CHANGED, this.reloadLibrary)
|
this.$eventHub.$off(LIBRARY_CHANGED, this.libraryChanged)
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
this.$store.commit('setLibraryRoute', {id: this.libraryId, route: LIBRARY_ROUTE.BROWSE})
|
this.$store.commit('setLibraryRoute', {id: this.libraryId, route: LIBRARY_ROUTE.BROWSE})
|
||||||
|
|
@ -365,8 +370,8 @@ export default Vue.extend({
|
||||||
})
|
})
|
||||||
return validFilter
|
return validFilter
|
||||||
},
|
},
|
||||||
libraryDeleted(event: EventLibraryDeleted) {
|
libraryDeleted(event: LibrarySseDto) {
|
||||||
if (event.id === this.libraryId) {
|
if (event.libraryId === this.libraryId) {
|
||||||
this.$router.push({name: 'home'})
|
this.$router.push({name: 'home'})
|
||||||
} else if (this.libraryId === LIBRARIES_ALL) {
|
} else if (this.libraryId === LIBRARIES_ALL) {
|
||||||
this.loadLibrary(this.libraryId)
|
this.loadLibrary(this.libraryId)
|
||||||
|
|
@ -407,13 +412,13 @@ export default Vue.extend({
|
||||||
|
|
||||||
this.setWatches()
|
this.setWatches()
|
||||||
},
|
},
|
||||||
reloadSeries(event: EventSeriesChanged) {
|
seriesChanged(event: SeriesSseDto) {
|
||||||
if (this.libraryId === LIBRARIES_ALL || event.libraryId === this.libraryId) {
|
if (this.libraryId === LIBRARIES_ALL || event.libraryId === this.libraryId) {
|
||||||
this.loadPage(this.libraryId, this.page, this.sortActive)
|
this.loadPage(this.libraryId, this.page, this.sortActive)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
reloadLibrary(event: EventLibraryChanged) {
|
libraryChanged(event: LibrarySseDto) {
|
||||||
if (this.libraryId === LIBRARIES_ALL || event.id === this.libraryId) {
|
if (this.libraryId === LIBRARIES_ALL || event.libraryId === this.libraryId) {
|
||||||
this.loadLibrary(this.libraryId)
|
this.loadLibrary(this.libraryId)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -76,12 +76,20 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import ItemBrowser from '@/components/ItemBrowser.vue'
|
import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||||
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
|
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
|
||||||
import {BOOK_CHANGED, READLIST_CHANGED, READLIST_DELETED} from '@/types/events'
|
import {
|
||||||
|
BOOK_CHANGED,
|
||||||
|
BOOK_DELETED,
|
||||||
|
READLIST_CHANGED,
|
||||||
|
READLIST_DELETED,
|
||||||
|
READPROGRESS_CHANGED,
|
||||||
|
READPROGRESS_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 {BookDto, ReadProgressUpdateDto} from '@/types/komga-books'
|
||||||
import {ContextOrigin} from '@/types/context'
|
import {ContextOrigin} from '@/types/context'
|
||||||
|
import {BookSseDto, ReadListSseDto, ReadProgressSseDto} from "@/types/komga-sse";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'BrowseReadList',
|
name: 'BrowseReadList',
|
||||||
|
|
@ -122,13 +130,19 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
this.$eventHub.$on(READLIST_CHANGED, this.readListChanged)
|
this.$eventHub.$on(READLIST_CHANGED, this.readListChanged)
|
||||||
this.$eventHub.$on(READLIST_DELETED, this.afterDelete)
|
this.$eventHub.$on(READLIST_DELETED, this.readListDeleted)
|
||||||
this.$eventHub.$on(BOOK_CHANGED, this.reloadBook)
|
this.$eventHub.$on(BOOK_CHANGED, this.bookChanged)
|
||||||
|
this.$eventHub.$on(BOOK_DELETED, this.bookChanged)
|
||||||
|
this.$eventHub.$on(READPROGRESS_CHANGED, this.readProgressChanged)
|
||||||
|
this.$eventHub.$on(READPROGRESS_DELETED, this.readProgressChanged)
|
||||||
},
|
},
|
||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
this.$eventHub.$off(READLIST_CHANGED, this.readListChanged)
|
this.$eventHub.$off(READLIST_CHANGED, this.readListChanged)
|
||||||
this.$eventHub.$off(READLIST_DELETED, this.afterDelete)
|
this.$eventHub.$off(READLIST_DELETED, this.readListDeleted)
|
||||||
this.$eventHub.$off(BOOK_CHANGED, this.reloadBook)
|
this.$eventHub.$off(BOOK_CHANGED, this.bookChanged)
|
||||||
|
this.$eventHub.$off(BOOK_DELETED, this.bookChanged)
|
||||||
|
this.$eventHub.$off(READPROGRESS_CHANGED, this.readProgressChanged)
|
||||||
|
this.$eventHub.$off(READPROGRESS_DELETED, this.readProgressChanged)
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.loadReadList(this.readListId)
|
this.loadReadList(this.readListId)
|
||||||
|
|
@ -150,11 +164,16 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
readListChanged (event: EventReadListChanged) {
|
readListChanged (event: ReadListSseDto) {
|
||||||
if (event.id === this.readListId) {
|
if (event.readListId === this.readListId) {
|
||||||
this.loadReadList(this.readListId)
|
this.loadReadList(this.readListId)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
readListDeleted (event: ReadListSseDto) {
|
||||||
|
if (event.readListId === this.readListId) {
|
||||||
|
this.$router.push({name: 'browse-readlists', params: {libraryId: 'all'}})
|
||||||
|
}
|
||||||
|
},
|
||||||
async loadReadList (readListId: string) {
|
async loadReadList (readListId: string) {
|
||||||
this.$komgaReadLists.getOneReadList(readListId)
|
this.$komgaReadLists.getOneReadList(readListId)
|
||||||
.then(v => this.readList = v)
|
.then(v => this.readList = v)
|
||||||
|
|
@ -206,11 +225,11 @@ export default Vue.extend({
|
||||||
editReadList () {
|
editReadList () {
|
||||||
this.$store.dispatch('dialogEditReadList', this.readList)
|
this.$store.dispatch('dialogEditReadList', this.readList)
|
||||||
},
|
},
|
||||||
afterDelete () {
|
bookChanged (event: BookSseDto) {
|
||||||
this.$router.push({ name: 'browse-readlists', params: { libraryId: 'all' } })
|
if (this.books.some(b => b.id === event.bookId)) this.loadReadList(this.readListId)
|
||||||
},
|
},
|
||||||
reloadBook (event: EventBookChanged) {
|
readProgressChanged(event: ReadProgressSseDto){
|
||||||
if (this.books.some(b => b.id === event.id)) this.loadReadList(this.readListId)
|
if (this.books.some(b => b.id === event.bookId)) this.loadReadList(this.readListId)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -54,10 +54,11 @@ import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||||
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
||||||
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
||||||
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
||||||
import {LIBRARY_CHANGED, READLIST_CHANGED, READLIST_DELETED} from '@/types/events'
|
import {LIBRARY_CHANGED, READLIST_ADDED, READLIST_CHANGED, READLIST_DELETED} from '@/types/events'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {Location} from 'vue-router'
|
import {Location} from 'vue-router'
|
||||||
import {LIBRARIES_ALL, LIBRARY_ROUTE} from '@/types/library'
|
import {LIBRARIES_ALL, LIBRARY_ROUTE} from '@/types/library'
|
||||||
|
import {LibrarySseDto} from "@/types/komga-sse";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'BrowseReadLists',
|
name: 'BrowseReadLists',
|
||||||
|
|
@ -87,11 +88,13 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
|
this.$eventHub.$on(READLIST_ADDED, this.reloadElements)
|
||||||
this.$eventHub.$on(READLIST_CHANGED, this.reloadElements)
|
this.$eventHub.$on(READLIST_CHANGED, this.reloadElements)
|
||||||
this.$eventHub.$on(READLIST_DELETED, this.reloadElements)
|
this.$eventHub.$on(READLIST_DELETED, this.reloadElements)
|
||||||
this.$eventHub.$on(LIBRARY_CHANGED, this.reloadLibrary)
|
this.$eventHub.$on(LIBRARY_CHANGED, this.reloadLibrary)
|
||||||
},
|
},
|
||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
|
this.$eventHub.$off(READLIST_ADDED, this.reloadElements)
|
||||||
this.$eventHub.$off(READLIST_CHANGED, this.reloadElements)
|
this.$eventHub.$off(READLIST_CHANGED, this.reloadElements)
|
||||||
this.$eventHub.$off(READLIST_DELETED, this.reloadElements)
|
this.$eventHub.$off(READLIST_DELETED, this.reloadElements)
|
||||||
this.$eventHub.$off(LIBRARY_CHANGED, this.reloadLibrary)
|
this.$eventHub.$off(LIBRARY_CHANGED, this.reloadLibrary)
|
||||||
|
|
@ -179,8 +182,8 @@ export default Vue.extend({
|
||||||
reloadElements () {
|
reloadElements () {
|
||||||
this.loadLibrary(this.libraryId)
|
this.loadLibrary(this.libraryId)
|
||||||
},
|
},
|
||||||
reloadLibrary (event: EventLibraryChanged) {
|
reloadLibrary (event: LibrarySseDto) {
|
||||||
if (event.id === this.libraryId) {
|
if (event.libraryId === this.libraryId) {
|
||||||
this.loadLibrary(this.libraryId)
|
this.loadLibrary(this.libraryId)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -381,7 +381,19 @@ import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
||||||
import {parseQueryParam, parseQueryParamAndFilter, parseQuerySort} from '@/functions/query-params'
|
import {parseQueryParam, parseQueryParamAndFilter, parseQuerySort} from '@/functions/query-params'
|
||||||
import {seriesFileUrl, seriesThumbnailUrl} from '@/functions/urls'
|
import {seriesFileUrl, seriesThumbnailUrl} from '@/functions/urls'
|
||||||
import {ReadStatus, replaceCompositeReadStatus} from '@/types/enum-books'
|
import {ReadStatus, replaceCompositeReadStatus} from '@/types/enum-books'
|
||||||
import {BOOK_CHANGED, LIBRARY_DELETED, READLIST_CHANGED, SERIES_CHANGED} from '@/types/events'
|
import {
|
||||||
|
BOOK_ADDED,
|
||||||
|
BOOK_CHANGED,
|
||||||
|
BOOK_DELETED,
|
||||||
|
COLLECTION_ADDED,
|
||||||
|
COLLECTION_CHANGED,
|
||||||
|
COLLECTION_DELETED,
|
||||||
|
LIBRARY_DELETED,
|
||||||
|
READPROGRESS_CHANGED,
|
||||||
|
READPROGRESS_DELETED,
|
||||||
|
SERIES_CHANGED,
|
||||||
|
SERIES_DELETED,
|
||||||
|
} from '@/types/events'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {Location} from 'vue-router'
|
import {Location} from 'vue-router'
|
||||||
import {AuthorDto, BookDto} from '@/types/komga-books'
|
import {AuthorDto, BookDto} from '@/types/komga-books'
|
||||||
|
|
@ -397,6 +409,8 @@ import ReadMore from "@/components/ReadMore.vue";
|
||||||
import {authorRoles, authorRolesSeries} from "@/types/author-roles";
|
import {authorRoles, authorRolesSeries} from "@/types/author-roles";
|
||||||
import VueHorizontal from "vue-horizontal";
|
import VueHorizontal from "vue-horizontal";
|
||||||
import RtlIcon from "@/components/RtlIcon.vue";
|
import RtlIcon from "@/components/RtlIcon.vue";
|
||||||
|
import {throttle} from "lodash";
|
||||||
|
import {BookSseDto, CollectionSseDto, LibrarySseDto, ReadProgressSseDto, SeriesSseDto} from "@/types/komga-sse";
|
||||||
|
|
||||||
const tags = require('language-tags')
|
const tags = require('language-tags')
|
||||||
|
|
||||||
|
|
@ -542,16 +556,30 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$eventHub.$on(SERIES_CHANGED, this.reloadSeries)
|
this.$eventHub.$on(SERIES_CHANGED, this.seriesChanged)
|
||||||
this.$eventHub.$on(READLIST_CHANGED, this.reloadSeries)
|
this.$eventHub.$on(SERIES_DELETED, this.seriesDeleted)
|
||||||
this.$eventHub.$on(BOOK_CHANGED, this.reloadBooks)
|
this.$eventHub.$on(BOOK_ADDED, this.bookChanged)
|
||||||
|
this.$eventHub.$on(BOOK_CHANGED, this.bookChanged)
|
||||||
|
this.$eventHub.$on(BOOK_DELETED, this.bookChanged)
|
||||||
|
this.$eventHub.$on(READPROGRESS_CHANGED, this.readProgressChanged)
|
||||||
|
this.$eventHub.$on(READPROGRESS_DELETED, this.readProgressChanged)
|
||||||
this.$eventHub.$on(LIBRARY_DELETED, this.libraryDeleted)
|
this.$eventHub.$on(LIBRARY_DELETED, this.libraryDeleted)
|
||||||
|
this.$eventHub.$on(COLLECTION_ADDED, this.collectionChanged)
|
||||||
|
this.$eventHub.$on(COLLECTION_CHANGED, this.collectionChanged)
|
||||||
|
this.$eventHub.$on(COLLECTION_DELETED, this.collectionChanged)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.$eventHub.$off(SERIES_CHANGED, this.reloadSeries)
|
this.$eventHub.$off(SERIES_CHANGED, this.seriesChanged)
|
||||||
this.$eventHub.$off(READLIST_CHANGED, this.reloadSeries)
|
this.$eventHub.$off(SERIES_DELETED, this.seriesDeleted)
|
||||||
this.$eventHub.$off(BOOK_CHANGED, this.reloadBooks)
|
this.$eventHub.$off(BOOK_ADDED, this.bookChanged)
|
||||||
|
this.$eventHub.$off(BOOK_CHANGED, this.bookChanged)
|
||||||
|
this.$eventHub.$off(BOOK_DELETED, this.bookChanged)
|
||||||
|
this.$eventHub.$off(READPROGRESS_CHANGED, this.readProgressChanged)
|
||||||
|
this.$eventHub.$off(READPROGRESS_DELETED, this.readProgressChanged)
|
||||||
this.$eventHub.$off(LIBRARY_DELETED, this.libraryDeleted)
|
this.$eventHub.$off(LIBRARY_DELETED, this.libraryDeleted)
|
||||||
|
this.$eventHub.$off(COLLECTION_ADDED, this.collectionChanged)
|
||||||
|
this.$eventHub.$off(COLLECTION_CHANGED, this.collectionChanged)
|
||||||
|
this.$eventHub.$off(COLLECTION_DELETED, this.collectionChanged)
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
this.pageSize = this.$store.state.persistedState.browsingPageSize || this.pageSize
|
this.pageSize = this.$store.state.persistedState.browsingPageSize || this.pageSize
|
||||||
|
|
@ -636,22 +664,41 @@ export default Vue.extend({
|
||||||
|
|
||||||
this.setWatches()
|
this.setWatches()
|
||||||
},
|
},
|
||||||
libraryDeleted(event: EventLibraryDeleted) {
|
libraryDeleted(event: LibrarySseDto) {
|
||||||
if (event.id === this.series.libraryId) {
|
if (event.libraryId === this.series.libraryId) {
|
||||||
this.$router.push({name: 'home'})
|
this.$router.push({name: 'home'})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
reloadSeries(event: EventSeriesChanged) {
|
seriesChanged(event: SeriesSseDto) {
|
||||||
if (event.id === this.seriesId) this.loadSeries(this.seriesId)
|
if (event.seriesId === this.seriesId)
|
||||||
|
this.$komgaSeries.getOneSeries(this.seriesId)
|
||||||
|
.then(v => this.series = v)
|
||||||
},
|
},
|
||||||
reloadBooks(event: EventBookChanged) {
|
seriesDeleted(event: SeriesSseDto) {
|
||||||
if (event.seriesId === this.seriesId) this.loadSeries(this.seriesId)
|
if (event.seriesId === this.seriesId) {
|
||||||
|
this.$router.push({name: 'browse-libraries', params: {libraryId: this.series.libraryId}})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
bookChanged(event: BookSseDto) {
|
||||||
|
if (event.seriesId === this.seriesId) this.reloadPage()
|
||||||
|
},
|
||||||
|
readProgressChanged(event: ReadProgressSseDto) {
|
||||||
|
if (this.books.some(b => b.id === event.bookId)) this.reloadPage()
|
||||||
|
},
|
||||||
|
collectionChanged(event: CollectionSseDto) {
|
||||||
|
if (event.seriesIds.includes(this.seriesId) || this.collections.map(x => x.id).includes(event.collectionId)) {
|
||||||
|
this.$komgaSeries.getCollections(this.seriesId)
|
||||||
|
.then(v => this.collections = v)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
reloadPage: throttle(function (this: any) {
|
||||||
|
this.loadPage(this.seriesId, this.page, this.sortActive)
|
||||||
|
}, 5000),
|
||||||
async loadSeries(seriesId: string) {
|
async loadSeries(seriesId: string) {
|
||||||
this.$komgaSeries.getOneSeries(seriesId)
|
this.$komgaSeries.getOneSeries(seriesId)
|
||||||
.then(v => this.series = v)
|
.then(v => this.series = v)
|
||||||
this.$komgaSeries.getCollections(seriesId)
|
this.$komgaSeries.getCollections(seriesId)
|
||||||
.then(v => this.collections = v)
|
.then(v => this.collections = v)
|
||||||
|
|
||||||
await this.loadPage(seriesId, this.page, this.sortActive)
|
await this.loadPage(seriesId, this.page, this.sortActive)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@
|
||||||
|
|
||||||
</toolbar-sticky>
|
</toolbar-sticky>
|
||||||
|
|
||||||
<library-navigation v-if="individualLibrary && $vuetify.breakpoint.name === 'xs'" :libraryId="libraryId" bottom-navigation/>
|
<library-navigation v-if="individualLibrary && $vuetify.breakpoint.name === 'xs'" :libraryId="libraryId"
|
||||||
|
bottom-navigation/>
|
||||||
|
|
||||||
<series-multi-select-bar
|
<series-multi-select-bar
|
||||||
v-model="selectedSeries"
|
v-model="selectedSeries"
|
||||||
|
|
@ -134,10 +135,21 @@ import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
||||||
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
||||||
import {ReadStatus} from '@/types/enum-books'
|
import {ReadStatus} from '@/types/enum-books'
|
||||||
import {BookDto} from '@/types/komga-books'
|
import {BookDto} from '@/types/komga-books'
|
||||||
import {BOOK_CHANGED, LIBRARY_DELETED, SERIES_CHANGED} from '@/types/events'
|
import {
|
||||||
|
BOOK_ADDED,
|
||||||
|
BOOK_CHANGED,
|
||||||
|
BOOK_DELETED,
|
||||||
|
READPROGRESS_CHANGED,
|
||||||
|
READPROGRESS_DELETED,
|
||||||
|
SERIES_ADDED,
|
||||||
|
SERIES_CHANGED,
|
||||||
|
SERIES_DELETED,
|
||||||
|
} from '@/types/events'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {SeriesDto} from "@/types/komga-series";
|
import {SeriesDto} from "@/types/komga-series";
|
||||||
import {LIBRARIES_ALL, LIBRARY_ROUTE} from "@/types/library";
|
import {LIBRARIES_ALL, LIBRARY_ROUTE} from "@/types/library";
|
||||||
|
import {throttle} from 'lodash'
|
||||||
|
import {BookSseDto, ReadProgressSseDto, SeriesSseDto} from "@/types/komga-sse";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
|
|
@ -164,17 +176,30 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$eventHub.$on(LIBRARY_DELETED, this.libraryDeleted)
|
this.$eventHub.$on(SERIES_ADDED, this.seriesChanged)
|
||||||
this.$eventHub.$on(SERIES_CHANGED, this.reload)
|
this.$eventHub.$on(SERIES_CHANGED, this.seriesChanged)
|
||||||
this.$eventHub.$on(BOOK_CHANGED, this.reload)
|
this.$eventHub.$on(SERIES_DELETED, this.seriesChanged)
|
||||||
|
this.$eventHub.$on(BOOK_ADDED, this.bookChanged)
|
||||||
|
this.$eventHub.$on(BOOK_CHANGED, this.bookChanged)
|
||||||
|
this.$eventHub.$on(BOOK_DELETED, this.bookChanged)
|
||||||
|
this.$eventHub.$on(READPROGRESS_CHANGED, this.readProgressChanged)
|
||||||
|
this.$eventHub.$on(READPROGRESS_DELETED, this.readProgressChanged)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.$eventHub.$off(LIBRARY_DELETED, this.libraryDeleted)
|
this.$eventHub.$off(SERIES_ADDED, this.seriesChanged)
|
||||||
this.$eventHub.$off(SERIES_CHANGED, this.reload)
|
this.$eventHub.$off(SERIES_CHANGED, this.seriesChanged)
|
||||||
this.$eventHub.$off(BOOK_CHANGED, this.reload)
|
this.$eventHub.$off(SERIES_DELETED, this.seriesChanged)
|
||||||
|
this.$eventHub.$off(BOOK_ADDED, this.bookChanged)
|
||||||
|
this.$eventHub.$off(BOOK_CHANGED, this.bookChanged)
|
||||||
|
this.$eventHub.$off(BOOK_DELETED, this.bookChanged)
|
||||||
|
this.$eventHub.$off(READPROGRESS_CHANGED, this.readProgressChanged)
|
||||||
|
this.$eventHub.$off(READPROGRESS_DELETED, this.readProgressChanged)
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if(this.individualLibrary) this.$store.commit('setLibraryRoute', {id: this.libraryId, route: LIBRARY_ROUTE.RECOMMENDED})
|
if (this.individualLibrary) this.$store.commit('setLibraryRoute', {
|
||||||
|
id: this.libraryId,
|
||||||
|
route: LIBRARY_ROUTE.RECOMMENDED,
|
||||||
|
})
|
||||||
this.reload()
|
this.reload()
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -193,6 +218,12 @@ export default Vue.extend({
|
||||||
libraryId(val) {
|
libraryId(val) {
|
||||||
this.loadAll(val)
|
this.loadAll(val)
|
||||||
},
|
},
|
||||||
|
'$store.state.komgaLibraries.libraries': {
|
||||||
|
handler(val){
|
||||||
|
if(val.length === 0) this.$router.push({name: 'welcome'})
|
||||||
|
else this.reload()
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
fixedCardWidth(): number {
|
fixedCardWidth(): number {
|
||||||
|
|
@ -213,16 +244,24 @@ export default Vue.extend({
|
||||||
getRequestLibraryId(libraryId: string): string | undefined {
|
getRequestLibraryId(libraryId: string): string | undefined {
|
||||||
return libraryId !== LIBRARIES_ALL ? libraryId : undefined
|
return libraryId !== LIBRARIES_ALL ? libraryId : undefined
|
||||||
},
|
},
|
||||||
libraryDeleted() {
|
seriesChanged(event: SeriesSseDto) {
|
||||||
if (this.$store.state.komgaLibraries.libraries.length === 0) {
|
if (this.libraryId === LIBRARIES_ALL || event.libraryId === this.libraryId) {
|
||||||
this.$router.push({name: 'welcome'})
|
|
||||||
} else {
|
|
||||||
this.reload()
|
this.reload()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
reload() {
|
bookChanged(event: BookSseDto){
|
||||||
this.loadAll(this.libraryId)
|
if (this.libraryId === LIBRARIES_ALL || event.libraryId === this.libraryId) {
|
||||||
|
this.reload()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
readProgressChanged(event: ReadProgressSseDto){
|
||||||
|
if (this.inProgressBooks.some(b => b.id === event.bookId)) this.reload()
|
||||||
|
else if (this.latestBooks.some(b => b.id === event.bookId)) this.reload()
|
||||||
|
else if (this.onDeckBooks.some(b => b.id === event.bookId)) this.reload()
|
||||||
|
},
|
||||||
|
reload: throttle(function(this: any) {
|
||||||
|
this.loadAll(this.libraryId)
|
||||||
|
}, 5000),
|
||||||
loadAll(libraryId: string) {
|
loadAll(libraryId: string) {
|
||||||
this.library = this.getLibraryLazy(libraryId)
|
this.library = this.getLibraryLazy(libraryId)
|
||||||
this.selectedSeries = []
|
this.selectedSeries = []
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,21 @@
|
||||||
Komga
|
Komga
|
||||||
</v-list-item-title>
|
</v-list-item-title>
|
||||||
</v-list-item-content>
|
</v-list-item-content>
|
||||||
|
|
||||||
|
<v-tooltip left>
|
||||||
|
<template v-slot:activator="{ on }">
|
||||||
|
<v-progress-linear
|
||||||
|
:active="taskCount > 0"
|
||||||
|
indeterminate
|
||||||
|
absolute
|
||||||
|
bottom
|
||||||
|
height="2"
|
||||||
|
color="secondary"
|
||||||
|
v-on="on"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<span>{{ $tc('common.pending_tasks', taskCount) }}</span>
|
||||||
|
</v-tooltip>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
|
|
||||||
<v-divider/>
|
<v-divider/>
|
||||||
|
|
@ -141,6 +156,7 @@
|
||||||
|
|
||||||
<v-main class="fill-height">
|
<v-main class="fill-height">
|
||||||
<dialogs/>
|
<dialogs/>
|
||||||
|
<toaster/>
|
||||||
<router-view/>
|
<router-view/>
|
||||||
</v-main>
|
</v-main>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -152,11 +168,12 @@ import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
||||||
import SearchBox from '@/components/SearchBox.vue'
|
import SearchBox from '@/components/SearchBox.vue'
|
||||||
import {Theme} from '@/types/themes'
|
import {Theme} from '@/types/themes'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {LIBRARIES_ALL} from "@/types/library";
|
import {LIBRARIES_ALL} from "@/types/library"
|
||||||
|
import Toaster from "@/components/Toaster.vue"
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'home',
|
name: 'home',
|
||||||
components: {LibraryActionsMenu, SearchBox, Dialogs},
|
components: {Toaster, LibraryActionsMenu, SearchBox, Dialogs},
|
||||||
data: function () {
|
data: function () {
|
||||||
return {
|
return {
|
||||||
LIBRARIES_ALL,
|
LIBRARIES_ALL,
|
||||||
|
|
@ -171,6 +188,9 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
taskCount(): number {
|
||||||
|
return this.$store.state.komgaSse.taskCount
|
||||||
|
},
|
||||||
libraries(): LibraryDto[] {
|
libraries(): LibraryDto[] {
|
||||||
return this.$store.state.komgaLibraries.libraries
|
return this.$store.state.komgaLibraries.libraries
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -110,15 +110,20 @@ import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||||
import {BookDto} from '@/types/komga-books'
|
import {BookDto} from '@/types/komga-books'
|
||||||
import {
|
import {
|
||||||
BOOK_CHANGED,
|
BOOK_CHANGED,
|
||||||
|
BOOK_DELETED,
|
||||||
COLLECTION_CHANGED,
|
COLLECTION_CHANGED,
|
||||||
COLLECTION_DELETED,
|
COLLECTION_DELETED,
|
||||||
LIBRARY_DELETED,
|
LIBRARY_DELETED,
|
||||||
READLIST_CHANGED,
|
READLIST_CHANGED,
|
||||||
READLIST_DELETED,
|
READLIST_DELETED,
|
||||||
|
READPROGRESS_CHANGED,
|
||||||
|
READPROGRESS_DELETED,
|
||||||
SERIES_CHANGED,
|
SERIES_CHANGED,
|
||||||
|
SERIES_DELETED,
|
||||||
} from '@/types/events'
|
} from '@/types/events'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {SeriesDto} from "@/types/komga-series";
|
import {SeriesDto} from "@/types/komga-series";
|
||||||
|
import {BookSseDto, CollectionSseDto, ReadListSseDto, ReadProgressSseDto, SeriesSseDto} from "@/types/komga-sse";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'Search',
|
name: 'Search',
|
||||||
|
|
@ -144,21 +149,29 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
this.$eventHub.$on(LIBRARY_DELETED, this.reloadResults)
|
this.$eventHub.$on(LIBRARY_DELETED, this.reloadResults)
|
||||||
this.$eventHub.$on(SERIES_CHANGED, this.reloadResults)
|
this.$eventHub.$on(SERIES_CHANGED, this.seriesChanged)
|
||||||
this.$eventHub.$on(BOOK_CHANGED, this.reloadResults)
|
this.$eventHub.$on(SERIES_DELETED, this.seriesChanged)
|
||||||
this.$eventHub.$on(COLLECTION_CHANGED, this.reloadResults)
|
this.$eventHub.$on(BOOK_CHANGED, this.bookChanged)
|
||||||
this.$eventHub.$on(COLLECTION_DELETED, this.reloadResults)
|
this.$eventHub.$on(BOOK_DELETED, this.bookChanged)
|
||||||
this.$eventHub.$on(READLIST_CHANGED, this.reloadResults)
|
this.$eventHub.$on(COLLECTION_CHANGED, this.collectionChanged)
|
||||||
this.$eventHub.$on(READLIST_DELETED, this.reloadResults)
|
this.$eventHub.$on(COLLECTION_DELETED, this.collectionChanged)
|
||||||
|
this.$eventHub.$on(READLIST_CHANGED, this.readListChanged)
|
||||||
|
this.$eventHub.$on(READLIST_DELETED, this.readListChanged)
|
||||||
|
this.$eventHub.$on(READPROGRESS_CHANGED, this.readProgressChanged)
|
||||||
|
this.$eventHub.$on(READPROGRESS_DELETED, this.readProgressChanged)
|
||||||
},
|
},
|
||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
this.$eventHub.$off(LIBRARY_DELETED, this.reloadResults)
|
this.$eventHub.$off(LIBRARY_DELETED, this.reloadResults)
|
||||||
this.$eventHub.$off(SERIES_CHANGED, this.reloadResults)
|
this.$eventHub.$off(SERIES_CHANGED, this.seriesChanged)
|
||||||
this.$eventHub.$off(BOOK_CHANGED, this.reloadResults)
|
this.$eventHub.$off(SERIES_DELETED, this.seriesChanged)
|
||||||
this.$eventHub.$off(COLLECTION_CHANGED, this.reloadResults)
|
this.$eventHub.$off(BOOK_CHANGED, this.bookChanged)
|
||||||
this.$eventHub.$off(COLLECTION_DELETED, this.reloadResults)
|
this.$eventHub.$off(BOOK_DELETED, this.bookChanged)
|
||||||
this.$eventHub.$off(READLIST_CHANGED, this.reloadResults)
|
this.$eventHub.$off(COLLECTION_CHANGED, this.collectionChanged)
|
||||||
this.$eventHub.$off(READLIST_DELETED, this.reloadResults)
|
this.$eventHub.$off(COLLECTION_DELETED, this.collectionChanged)
|
||||||
|
this.$eventHub.$off(READLIST_CHANGED, this.readListChanged)
|
||||||
|
this.$eventHub.$off(READLIST_DELETED, this.readListChanged)
|
||||||
|
this.$eventHub.$off(READPROGRESS_CHANGED, this.readProgressChanged)
|
||||||
|
this.$eventHub.$off(READPROGRESS_DELETED, this.readProgressChanged)
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$route.query.q': {
|
'$route.query.q': {
|
||||||
|
|
@ -199,6 +212,31 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
seriesChanged(event: SeriesSseDto){
|
||||||
|
if(this.series.map(x => x.id).includes(event.seriesId)){
|
||||||
|
this.reloadResults()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
bookChanged(event: BookSseDto){
|
||||||
|
if(this.books.map(x => x.id).includes(event.bookId)){
|
||||||
|
this.reloadResults()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
readProgressChanged(event: ReadProgressSseDto){
|
||||||
|
if(this.books.map(x => x.id).includes(event.bookId)){
|
||||||
|
this.reloadResults()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
collectionChanged (event: CollectionSseDto) {
|
||||||
|
if (this.collections.map(x => x.id).includes(event.collectionId)) {
|
||||||
|
this.reloadResults()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
readListChanged (event: ReadListSseDto) {
|
||||||
|
if (this.readLists.map(x => x.id).includes(event.readListId)) {
|
||||||
|
this.reloadResults()
|
||||||
|
}
|
||||||
|
},
|
||||||
singleEditSeries (series: SeriesDto) {
|
singleEditSeries (series: SeriesDto) {
|
||||||
this.$store.dispatch('dialogUpdateSeries', series)
|
this.$store.dispatch('dialogUpdateSeries', series)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="ma-3">
|
<div class="pa-6">
|
||||||
<v-row align="center" justify="center">
|
<v-row align="center" justify="center">
|
||||||
<v-img src="../assets/logo.svg"
|
<v-img src="../assets/logo.svg"
|
||||||
max-width="400"
|
max-width="400"
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {LIBRARY_ADDED} from '@/types/events'
|
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
|
|
@ -26,21 +25,19 @@ export default Vue.extend({
|
||||||
return this.$store.getters.meAdmin
|
return this.$store.getters.meAdmin
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created () {
|
|
||||||
this.$eventHub.$on(LIBRARY_ADDED, this.libraryAdded)
|
|
||||||
},
|
|
||||||
beforeDestroy () {
|
|
||||||
this.$eventHub.$off(LIBRARY_ADDED, this.libraryAdded)
|
|
||||||
},
|
|
||||||
mounted () {
|
mounted () {
|
||||||
if (this.$store.state.komgaLibraries.libraries.length !== 0) {
|
if (this.$store.state.komgaLibraries.libraries.length !== 0) {
|
||||||
this.$router.push({ name: 'dashboard' })
|
this.$router.push({ name: 'dashboard' })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
watch: {
|
||||||
libraryAdded () {
|
'$store.state.komgaLibraries.libraries': {
|
||||||
this.$router.push({ name: 'dashboard' })
|
handler(val){
|
||||||
|
if(val.length !== 0) this.$router.push({name: 'dashboard'})
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
addLibrary () {
|
addLibrary () {
|
||||||
this.$store.dispatch('dialogAddLibrary')
|
this.$store.dispatch('dialogAddLibrary')
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue