feat(webui): add filters to media analysis table

Closes: #1802
This commit is contained in:
Gauthier Roebroeck 2025-01-22 13:42:26 +08:00
parent dbd225dcb4
commit 68e05b8e28

View file

@ -13,6 +13,34 @@
itemsPerPageOptions: [20, 50, 100]
}"
>
<template v-slot:top>
<v-container>
<v-row>
<v-col cols="12" sm="6">
<v-chip-group v-model="filterStatus" color="primary" mandatory multiple>
<v-chip filter value="error">{{ $t('common.error') }}</v-chip>
<v-chip filter value="unsupported">{{ $t('book_card.unsupported') }}</v-chip>
</v-chip-group>
</v-col>
<v-col cols="12" sm="6">
<v-select v-model="filterLibraries"
:items="filterLibrariesOptions"
:label="$t('navigation.libraries')"
clearable
solo
multiple
chips
deletable-chips
/>
</v-col>
</v-row>
</v-container>
</template>
<template v-slot:item.libraryId="{ item }">
{{ getLibraryName(item.libraryId) }}
</template>
<template v-slot:item.name="{ item }">
<router-link
:to="{name: item.oneshot ? 'browse-oneshot' : 'browse-book', params: {bookId: item.id, seriesId: item.seriesId}}">
@ -29,7 +57,9 @@
</template>
<template v-slot:footer.prepend>
<v-btn icon @click="loadBooks"><v-icon>mdi-refresh</v-icon></v-btn>
<v-btn icon @click="loadBooks">
<v-icon>mdi-refresh</v-icon>
</v-btn>
</template>
</v-data-table>
</v-container>
@ -40,7 +70,15 @@ import Vue from 'vue'
import {MediaStatus} from '@/types/enum-books'
import {BookDto} from '@/types/komga-books'
import {convertErrorCodes} from '@/functions/error-codes'
import {BookSearch, SearchConditionAnyOfBook, SearchConditionMediaStatus, SearchOperatorIs} from '@/types/komga-search'
import {
BookSearch,
SearchConditionAllOfBook,
SearchConditionAnyOfBook,
SearchConditionBook,
SearchConditionLibraryId,
SearchConditionMediaStatus,
SearchOperatorIs,
} from '@/types/komga-search'
export default Vue.extend({
name: 'MediaAnalysis',
@ -50,6 +88,8 @@ export default Vue.extend({
totalBooks: 0,
loading: true,
options: {} as any,
filterStatus: ['error', 'unsupported'],
filterLibraries: [] as string[],
}
},
watch: {
@ -59,10 +99,23 @@ export default Vue.extend({
},
deep: true,
},
filterStatus() {
this.loadBooks()
},
filterLibraries() {
this.loadBooks()
},
},
computed: {
filterLibrariesOptions(): object[] {
return this.$store.state.komgaLibraries.libraries.map(x => ({
text: x.name,
value: x.id,
}))
},
headers(): object[] {
return [
{text: this.$i18n.t('common.library').toString(), value: 'libraryId', sortable: false},
{text: this.$i18n.t('media_analysis.name').toString(), value: 'name'},
{text: this.$i18n.t('media_analysis.status').toString(), value: 'media.status'},
{text: this.$i18n.t('media_analysis.comment').toString(), value: 'media.comment'},
@ -72,17 +125,21 @@ export default Vue.extend({
{text: '', value: 'deleted', groupable: false, sortable: false},
]
},
booksData():BookDto[] {
return this.books.map((b:BookDto) => ({
booksData(): BookDto[] {
return this.books.map((b: BookDto) => ({
...b,
media: {
...b.media,
comment: convertErrorCodes(b.media.comment),
status: this.$t(`enums.media_status.${b.media.status}`).toString()},
status: this.$t(`enums.media_status.${b.media.status}`).toString(),
},
}))
},
},
methods: {
getLibraryName(libraryId: string): string {
return this.$store.getters.getLibraryById(libraryId).name
},
async loadBooks() {
this.loading = true
@ -98,15 +155,24 @@ export default Vue.extend({
pageRequest.sort!!.push(`${sortBy[i]},${sortDesc[i] ? 'desc' : 'asc'}`)
}
const booksPage = await this.$komgaBooks.getBooksList({
condition: new SearchConditionAnyOfBook([
new SearchConditionMediaStatus(new SearchOperatorIs(MediaStatus.ERROR)),
new SearchConditionMediaStatus(new SearchOperatorIs(MediaStatus.UNSUPPORTED)),
]),
} as BookSearch, pageRequest)
this.totalBooks = booksPage.totalElements
this.$store.commit('setBooksToCheck', booksPage.totalElements)
this.books = booksPage.content
const conditionsStatus = [] as SearchConditionBook[]
if (this.filterStatus.includes('error')) conditionsStatus.push(new SearchConditionMediaStatus(new SearchOperatorIs(MediaStatus.ERROR)))
if (this.filterStatus.includes('unsupported')) conditionsStatus.push(new SearchConditionMediaStatus(new SearchOperatorIs(MediaStatus.UNSUPPORTED)))
const conditionsLibraries = [] as SearchConditionBook[]
this.filterLibraries.forEach(x => conditionsLibraries.push(new SearchConditionLibraryId(new SearchOperatorIs(x))))
if (this.filterStatus.length > 0) {
const booksPage = await this.$komgaBooks.getBooksList({
condition: new SearchConditionAllOfBook([
new SearchConditionAnyOfBook(conditionsStatus),
new SearchConditionAnyOfBook(conditionsLibraries),
]),
} as BookSearch, pageRequest)
this.totalBooks = booksPage.totalElements
this.$store.commit('setBooksToCheck', booksPage.totalElements)
this.books = booksPage.content
}
this.loading = false
},