mirror of
https://github.com/gotson/komga.git
synced 2025-12-20 23:45:11 +01:00
322 lines
11 KiB
Vue
322 lines
11 KiB
Vue
<template>
|
|
<div>
|
|
<toolbar-sticky v-if="showToolbar">
|
|
<v-toolbar-title>
|
|
<span>{{ $t('search.search_results_for', {name: $route.query.q}) }}</span>
|
|
</v-toolbar-title>
|
|
</toolbar-sticky>
|
|
|
|
<series-multi-select-bar
|
|
v-model="selectedSeries"
|
|
@unselect-all="selectedSeries = []"
|
|
@mark-read="markSelectedSeriesRead"
|
|
@mark-unread="markSelectedSeriesUnread"
|
|
@add-to-collection="addToCollection"
|
|
@edit="editMultipleSeries"
|
|
/>
|
|
|
|
<books-multi-select-bar
|
|
v-model="selectedBooks"
|
|
@unselect-all="selectedBooks = []"
|
|
@mark-read="markSelectedBooksRead"
|
|
@mark-unread="markSelectedBooksUnread"
|
|
@add-to-readlist="addToReadList"
|
|
@edit="editMultipleBooks"
|
|
/>
|
|
|
|
<v-container fluid>
|
|
<empty-state
|
|
v-if="emptyResults"
|
|
:title="$t('search.no_results')"
|
|
:sub-title="$t('search.search_for_something_else')"
|
|
icon="mdi-magnify"
|
|
icon-color="secondary"
|
|
class="my-4"
|
|
>
|
|
</empty-state>
|
|
|
|
<template v-else>
|
|
<horizontal-scroller v-if="series.length !== 0" class="mb-4">
|
|
<template v-slot:prepend>
|
|
<div class="title">{{ $t('common.series') }}</div>
|
|
</template>
|
|
<template v-slot:content>
|
|
<item-browser :items="series"
|
|
nowrap
|
|
:edit-function="singleEditSeries"
|
|
:selected.sync="selectedSeries"
|
|
:selectable="selectedBooks.length === 0"
|
|
:fixed-item-width="fixedCardWidth"
|
|
/>
|
|
</template>
|
|
</horizontal-scroller>
|
|
|
|
<horizontal-scroller v-if="books.length !== 0" class="mb-4">
|
|
<template v-slot:prepend>
|
|
<div class="title">{{ $t('common.books') }}</div>
|
|
</template>
|
|
<template v-slot:content>
|
|
<item-browser :items="books"
|
|
nowrap
|
|
:edit-function="singleEditBook"
|
|
:selected.sync="selectedBooks"
|
|
:selectable="selectedSeries.length === 0"
|
|
:fixed-item-width="fixedCardWidth"
|
|
/>
|
|
</template>
|
|
</horizontal-scroller>
|
|
|
|
<horizontal-scroller v-if="collections.length !== 0" class="mb-4">
|
|
<template v-slot:prepend>
|
|
<div class="title">{{ $t('common.collections') }}</div>
|
|
</template>
|
|
<template v-slot:content>
|
|
<item-browser :items="collections"
|
|
nowrap
|
|
:edit-function="singleEditCollection"
|
|
:selectable="false"
|
|
:fixed-item-width="fixedCardWidth"
|
|
/>
|
|
</template>
|
|
</horizontal-scroller>
|
|
|
|
<horizontal-scroller v-if="readLists.length !== 0" class="mb-4">
|
|
<template v-slot:prepend>
|
|
<div class="title">{{ $t('common.readlists') }}</div>
|
|
</template>
|
|
<template v-slot:content>
|
|
<item-browser :items="readLists"
|
|
nowrap
|
|
:edit-function="singleEditReadList"
|
|
:selectable="false"
|
|
:fixed-item-width="fixedCardWidth"
|
|
/>
|
|
</template>
|
|
</horizontal-scroller>
|
|
|
|
</template>
|
|
</v-container>
|
|
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import BooksMultiSelectBar from '@/components/bars/BooksMultiSelectBar.vue'
|
|
import SeriesMultiSelectBar from '@/components/bars/SeriesMultiSelectBar.vue'
|
|
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
|
|
import EmptyState from '@/components/EmptyState.vue'
|
|
import HorizontalScroller from '@/components/HorizontalScroller.vue'
|
|
import ItemBrowser from '@/components/ItemBrowser.vue'
|
|
import {BookDto} from '@/types/komga-books'
|
|
import {
|
|
BOOK_CHANGED,
|
|
BOOK_DELETED,
|
|
COLLECTION_CHANGED,
|
|
COLLECTION_DELETED,
|
|
LIBRARY_DELETED,
|
|
READLIST_CHANGED,
|
|
READLIST_DELETED,
|
|
READPROGRESS_CHANGED,
|
|
READPROGRESS_DELETED,
|
|
SERIES_CHANGED,
|
|
SERIES_DELETED,
|
|
} from '@/types/events'
|
|
import Vue from 'vue'
|
|
import {SeriesDto} from "@/types/komga-series";
|
|
import {BookSseDto, CollectionSseDto, ReadListSseDto, ReadProgressSseDto, SeriesSseDto} from "@/types/komga-sse";
|
|
|
|
export default Vue.extend({
|
|
name: 'Search',
|
|
components: {
|
|
EmptyState,
|
|
ToolbarSticky,
|
|
HorizontalScroller,
|
|
ItemBrowser,
|
|
BooksMultiSelectBar,
|
|
SeriesMultiSelectBar,
|
|
},
|
|
data: () => {
|
|
return {
|
|
series: [] as SeriesDto[],
|
|
books: [] as BookDto[],
|
|
collections: [] as CollectionDto[],
|
|
readLists: [] as ReadListDto[],
|
|
pageSize: 50,
|
|
loading: false,
|
|
selectedSeries: [] as SeriesDto[],
|
|
selectedBooks: [] as BookDto[],
|
|
}
|
|
},
|
|
created () {
|
|
this.$eventHub.$on(LIBRARY_DELETED, this.reloadResults)
|
|
this.$eventHub.$on(SERIES_CHANGED, this.seriesChanged)
|
|
this.$eventHub.$on(SERIES_DELETED, this.seriesChanged)
|
|
this.$eventHub.$on(BOOK_CHANGED, this.bookChanged)
|
|
this.$eventHub.$on(BOOK_DELETED, this.bookChanged)
|
|
this.$eventHub.$on(COLLECTION_CHANGED, this.collectionChanged)
|
|
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 () {
|
|
this.$eventHub.$off(LIBRARY_DELETED, this.reloadResults)
|
|
this.$eventHub.$off(SERIES_CHANGED, this.seriesChanged)
|
|
this.$eventHub.$off(SERIES_DELETED, this.seriesChanged)
|
|
this.$eventHub.$off(BOOK_CHANGED, this.bookChanged)
|
|
this.$eventHub.$off(BOOK_DELETED, this.bookChanged)
|
|
this.$eventHub.$off(COLLECTION_CHANGED, this.collectionChanged)
|
|
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: {
|
|
'$route.query.q': {
|
|
handler: function (val) {
|
|
this.loadResults(val)
|
|
this.selectedBooks = []
|
|
this.selectedSeries = []
|
|
},
|
|
deep: true,
|
|
immediate: true,
|
|
},
|
|
selectedSeries (val: SeriesDto[]) {
|
|
val.forEach(s => {
|
|
const index = this.series.findIndex(x => x.id === s.id)
|
|
if (index !== -1) {
|
|
this.series.splice(index, 1, s)
|
|
}
|
|
})
|
|
},
|
|
selectedBooks (val: BookDto[]) {
|
|
val.forEach(b => {
|
|
const index = this.books.findIndex(x => x.id === b.id)
|
|
if (index !== -1) {
|
|
this.books.splice(index, 1, b)
|
|
}
|
|
})
|
|
},
|
|
},
|
|
computed: {
|
|
fixedCardWidth (): number {
|
|
return this.$vuetify.breakpoint.name === 'xs' ? 120 : 150
|
|
},
|
|
showToolbar (): boolean {
|
|
return this.selectedSeries.length === 0 && this.selectedBooks.length === 0
|
|
},
|
|
emptyResults (): boolean {
|
|
return !this.loading && this.series.length === 0 && this.books.length === 0 && this.collections.length === 0 && this.readLists.length === 0
|
|
},
|
|
},
|
|
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) {
|
|
this.$store.dispatch('dialogUpdateSeries', series)
|
|
},
|
|
singleEditBook (book: BookDto) {
|
|
this.$store.dispatch('dialogUpdateBooks', book)
|
|
},
|
|
singleEditCollection (collection: CollectionDto) {
|
|
this.$store.dispatch('dialogEditCollection', collection)
|
|
},
|
|
singleEditReadList (readList: ReadListDto) {
|
|
this.$store.dispatch('dialogEditReadList', readList)
|
|
},
|
|
async markSelectedSeriesRead () {
|
|
await Promise.all(this.selectedSeries.map(s =>
|
|
this.$komgaSeries.markAsRead(s.id),
|
|
))
|
|
this.selectedSeries = await Promise.all(this.selectedSeries.map(s =>
|
|
this.$komgaSeries.getOneSeries(s.id),
|
|
))
|
|
},
|
|
async markSelectedSeriesUnread () {
|
|
await Promise.all(this.selectedSeries.map(s =>
|
|
this.$komgaSeries.markAsUnread(s.id),
|
|
))
|
|
this.selectedSeries = await Promise.all(this.selectedSeries.map(s =>
|
|
this.$komgaSeries.getOneSeries(s.id),
|
|
))
|
|
},
|
|
addToCollection () {
|
|
this.$store.dispatch('dialogAddSeriesToCollection', this.selectedSeries)
|
|
},
|
|
addToReadList () {
|
|
this.$store.dispatch('dialogAddBooksToReadList', this.selectedBooks)
|
|
},
|
|
editMultipleSeries () {
|
|
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
|
|
},
|
|
editMultipleBooks () {
|
|
this.$store.dispatch('dialogUpdateBooks', this.selectedBooks)
|
|
},
|
|
async markSelectedBooksRead () {
|
|
await Promise.all(this.selectedBooks.map(b =>
|
|
this.$komgaBooks.updateReadProgress(b.id, { completed: true }),
|
|
))
|
|
this.selectedBooks = await Promise.all(this.selectedBooks.map(b =>
|
|
this.$komgaBooks.getBook(b.id),
|
|
))
|
|
},
|
|
async markSelectedBooksUnread () {
|
|
await Promise.all(this.selectedBooks.map(b =>
|
|
this.$komgaBooks.deleteReadProgress(b.id),
|
|
))
|
|
this.selectedBooks = await Promise.all(this.selectedBooks.map(b =>
|
|
this.$komgaBooks.getBook(b.id),
|
|
))
|
|
},
|
|
reloadResults () {
|
|
this.loadResults(this.$route.query.q.toString())
|
|
},
|
|
async loadResults (search: string) {
|
|
this.selectedBooks = []
|
|
this.selectedSeries = []
|
|
if (search) {
|
|
this.loading = true
|
|
|
|
this.series = (await this.$komgaSeries.getSeries(undefined, { size: this.pageSize }, search)).content
|
|
this.books = (await this.$komgaBooks.getBooks(undefined, { size: this.pageSize }, search)).content
|
|
this.collections = (await this.$komgaCollections.getCollections(undefined, { size: this.pageSize }, search)).content
|
|
this.readLists = (await this.$komgaReadLists.getReadLists(undefined, { size: this.pageSize }, search)).content
|
|
|
|
this.loading = false
|
|
} else {
|
|
this.series = []
|
|
this.books = []
|
|
this.collections = []
|
|
this.readLists = []
|
|
}
|
|
},
|
|
},
|
|
})
|
|
</script>
|
|
<style scoped>
|
|
</style>
|