add searchbox

This commit is contained in:
Gauthier Roebroeck 2019-12-12 13:47:45 +08:00
parent 08e794d6c7
commit 30d38a7b70
4 changed files with 126 additions and 3 deletions

View file

@ -0,0 +1,113 @@
<template>
<div id="searchbox">
<v-text-field v-model="search"
solo
hide-details
clearable
prepend-inner-icon="mdi-magnify"
label="Search"
:loading="loading"
@click:clear="clear"
@keydown.esc="clear"
/>
<v-menu nudge-bottom="57"
nudge-right="52"
attach="#searchbox"
v-model="showResults"
:max-height="$vuetify.breakpoint.height * .9"
:min-width="$vuetify.breakpoint.mdAndUp ? $vuetify.breakpoint.width * .4 : $vuetify.breakpoint.width * .8"
>
<v-list>
<v-list-item v-if="series.length === 0 && books.length === 0">No results</v-list-item>
<template v-if="series.length !== 0">
<v-subheader>SERIES</v-subheader>
<v-list-item v-for="item in series"
:key="item.id"
link
:to="{name: 'browse-series', params: {seriesId: item.id}}"
>
<v-img :src="baseURL + '/api/v1/series/' + item.id + '/thumbnail'"
height="50"
max-width="35"
class="ma-1 mr-3"
/>
<v-list-item-content>
<v-list-item-title v-text="item.name"/>
</v-list-item-content>
</v-list-item>
</template>
<template v-if="books.length !== 0">
<v-subheader>BOOKS</v-subheader>
<v-list-item v-for="item in books"
:key="item.id"
link
:to="{name: 'browse-book', params: {bookId: item.id}}"
>
<v-img :src="baseURL + '/api/v1/books/' + item.id + '/thumbnail'"
height="50"
max-width="35"
class="ma-1 mr-3"
/>
<v-list-item-content>
<v-list-item-title v-text="item.name"/>
</v-list-item-content>
</v-list-item>
</template>
</v-list>
</v-menu>
</div>
</template>
<script lang="ts">
import { debounce } from 'lodash'
import Vue from 'vue'
export default Vue.extend({
name: 'SearchBox',
data: function () {
return {
baseURL: process.env.VUE_APP_KOMGA_API_URL ? process.env.VUE_APP_KOMGA_API_URL : window.location.origin,
search: null,
showResults: false,
loading: false,
series: [] as SeriesDto[],
books: [] as BookDto[],
pageSize: 5
}
},
watch: {
search (val) {
this.searchItems(val)
},
showResults (val) {
!val && this.clear()
}
},
methods: {
searchItems: debounce(async function (this: any, query: string) {
if (query) {
this.loading = true
this.series = (await this.$komgaSeries.getSeries(undefined, { size: this.pageSize }, query)).content
this.books = (await this.$komgaBooks.getBooks(undefined, { size: this.pageSize }, query)).content
this.showResults = true
this.loading = false
} else {
this.clear()
}
}, 500),
clear () {
this.search = null
this.showResults = false
this.series = []
this.books = []
}
}
})
</script>
<style scoped>
</style>

View file

@ -11,12 +11,15 @@ export default class KomgaBooksService {
this.http = http
}
async getBooks (libraryId?: number, pageRequest?: PageRequest): Promise<Page<BookDto>> {
async getBooks (libraryId?: number, pageRequest?: PageRequest, search?: string): Promise<Page<BookDto>> {
try {
const params = { ...pageRequest } as any
if (libraryId) {
params.library_id = libraryId
}
if (search) {
params.search = search
}
return (await this.http.get(API_BOOKS, {
params: params,
paramsSerializer: params => qs.stringify(params, { indices: false })

View file

@ -11,12 +11,15 @@ export default class KomgaSeriesService {
this.http = http
}
async getSeries (libraryId?: number, pageRequest?: PageRequest): Promise<Page<SeriesDto>> {
async getSeries (libraryId?: number, pageRequest?: PageRequest, search?: string): Promise<Page<SeriesDto>> {
try {
const params = { ...pageRequest } as any
if (libraryId) {
params.library_id = libraryId
}
if (search) {
params.search = search
}
return (await this.http.get(API_SERIES, {
params: params,
paramsSerializer: params => qs.stringify(params, { indices: false })

View file

@ -4,6 +4,9 @@
app
>
<v-app-bar-nav-icon @click.stop="toggleDrawer"/>
<search-box class="flex-fill"/>
</v-app-bar>
<v-navigation-drawer app v-model="drawerVisible">
@ -109,11 +112,12 @@
<script lang="ts">
import LibraryDeleteDialog from '@/components/LibraryDeleteDialog.vue'
import SearchBox from '@/components/SearchBox.vue'
import Vue from 'vue'
export default Vue.extend({
name: 'home',
components: { LibraryDeleteDialog },
components: { LibraryDeleteDialog, SearchBox },
data: function () {
return {
drawerVisible: this.$vuetify.breakpoint.lgAndUp,