Skip to content

Commit

Permalink
feat(webui): filter series by status
Browse files Browse the repository at this point in the history
when browsing libraries

linked to #48
  • Loading branch information
gotson committed Jan 22, 2020
1 parent c96bf19 commit c540e56
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 15 deletions.
87 changes: 73 additions & 14 deletions komga-webui/src/components/BrowseLibraries.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SeriesStatus } from '@/types/common'
<template>
<div>
<v-toolbar flat
Expand All @@ -12,14 +13,41 @@
<v-toolbar-title>
<span>{{ library ? library.name : 'All libraries' }}</span>
<span class="ml-4 badge-count"
v-if="totalElements"
v-if="totalElements !== null"
>
{{ totalElements }}
</span>
</v-toolbar-title>

<v-spacer/>

<!-- Filter menu -->
<v-menu offset-y
:close-on-content-click="false"
>
<template v-slot:activator="{on}">
<v-btn icon v-on="on">
<v-icon :color="$_.isEmpty(filterStatus) ? null : 'secondary'"
>mdi-filter-variant
</v-icon>
</v-btn>
</template>
<v-list>
<v-subheader>STATUS</v-subheader>
<v-list-item v-for="s in SeriesStatus"
:key="s"
>
<v-list-item-title class="text-capitalize">
<v-checkbox v-model="filterStatus"
:label="s.toString().toLowerCase()"
color="secondary"
class="mt-1 ml-2"
:value="s"/>
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>

<!-- Sort menu -->
<v-menu offset-y>
<template v-slot:activator="{on}">
Expand Down Expand Up @@ -49,7 +77,7 @@
</v-toolbar>

<v-container fluid class="px-6">
<v-row justify="start" ref="content" v-resize="updateCardWidth">
<v-row justify="start" ref="content" v-resize="updateCardWidth" v-if="totalElements !== 0">

<v-skeleton-loader v-for="(s, i) in series"
:key="i"
Expand All @@ -66,14 +94,28 @@
</v-skeleton-loader>

</v-row>

<!-- Empty state if filter returns no books -->
<v-row justify="center" v-else>
<div class="text-center">
<v-avatar color="grey lighten-3" size="400">
<div>
<v-icon color="primary" size="140">mdi-book-multiple</v-icon>
<h1 class="headline">The active filter has no matches</h1>
<p class="body-1">Use the menu above to change the active filter</p>
<v-btn color="primary" @click="filterStatus = []">Clear filter</v-btn>
</div>
</v-avatar>
</div>
</v-row>
</v-container>
</div>
</template>

<script lang="ts">
import CardSeries from '@/components/CardSeries.vue'
import LibraryActionsMenu from '@/components/LibraryActionsMenu.vue'
import { LoadState } from '@/types/common'
import { LoadState, SeriesStatus } from '@/types/common'
import Vue from 'vue'
export default Vue.extend({
Expand All @@ -93,6 +135,8 @@ export default Vue.extend({
}] as SortOption[],
sortActive: {} as SortActive as SortActive,
sortDefault: { key: 'name', order: 'asc' } as SortActive as SortActive,
filterStatus: [] as string[],
SeriesStatus,
cardWidth: 150
}
},
Expand All @@ -114,6 +158,12 @@ export default Vue.extend({
default: 0
}
},
watch: {
filterStatus () {
this.updateRoute()
this.reloadData(this.libraryId)
}
},
async created () {
this.library = await this.getLibraryLazy(this.libraryId)
},
Expand All @@ -127,11 +177,15 @@ export default Vue.extend({
// restore sort from query param
this.sortActive = this.parseQuerySortOrDefault(this.$route.query.sort)
// restore filter status from query params
this.filterStatus = this.parseQueryFilterStatus(this.$route.query.status)
},
beforeRouteUpdate (to, from, next) {
if (to.params.libraryId !== from.params.libraryId) {
this.library = this.getLibraryLazy(Number(to.params.libraryId))
this.sortActive = this.parseQuerySortOrDefault(to.query.sort)
this.filterStatus = this.parseQueryFilterStatus(to.query.status)
this.reloadData(Number(to.params.libraryId))
}
Expand Down Expand Up @@ -165,6 +219,9 @@ export default Vue.extend({
return this.$_.clone(this.sortDefault)
}
},
parseQueryFilterStatus (queryStatus: any): string[] {
return queryStatus ? queryStatus.toString().split(',').filter((x: string) => Object.keys(SeriesStatus).includes(x)) : []
},
async onCardIntersect (entries: any, observer: any, isIntersecting: boolean) {
const elementIndex = Number(entries[0].target.dataset['index'])
if (isIntersecting) {
Expand All @@ -181,11 +238,7 @@ export default Vue.extend({
const index = (max === undefined ? 0 : max).toString()
if (this.$route.params.index !== index) {
this.$router.replace({
name: this.$route.name,
params: { libraryId: this.$route.params.libraryId, index: index },
query: { sort: `${this.sortActive.key},${this.sortActive.order}` }
})
this.updateRoute(index)
}
},
reloadData (libraryId: number) {
Expand All @@ -195,6 +248,16 @@ export default Vue.extend({
this.series = Array(this.pageSize).fill(null)
this.loadInitialData(libraryId)
},
updateRoute (index?: string) {
this.$router.replace({
name: this.$route.name,
params: { libraryId: this.$route.params.libraryId, index: index || this.$route.params.index },
query: {
sort: `${this.sortActive.key},${this.sortActive.order}`,
status: `${this.filterStatus}`
}
})
},
setSort (sort: SortOption) {
if (this.sortActive.key === sort.key) {
if (this.sortActive.order === 'desc') {
Expand All @@ -205,11 +268,7 @@ export default Vue.extend({
} else {
this.sortActive = { key: sort.key, order: 'desc' }
}
this.$router.replace({
name: this.$route.name,
params: { libraryId: this.$route.params.libraryId, index: this.$route.params.index },
query: { sort: `${this.sortActive.key},${this.sortActive.order}` }
})
this.updateRoute()
this.reloadData(this.libraryId)
},
async loadInitialData (libraryId: number, pageToLoad: number = 0) {
Expand All @@ -230,7 +289,7 @@ export default Vue.extend({
if (libraryId !== 0) {
requestLibraryId = libraryId
}
return this.$komgaSeries.getSeries(requestLibraryId, pageRequest)
return this.$komgaSeries.getSeries(requestLibraryId, pageRequest, undefined, this.filterStatus)
},
processPage (page: Page<SeriesDto>) {
if (this.totalElements === null) {
Expand Down
5 changes: 4 additions & 1 deletion komga-webui/src/services/komga-series.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default class KomgaSeriesService {
this.http = http
}

async getSeries (libraryId?: number, pageRequest?: PageRequest, search?: string): Promise<Page<SeriesDto>> {
async getSeries (libraryId?: number, pageRequest?: PageRequest, search?: string, status?: string[]): Promise<Page<SeriesDto>> {
try {
const params = { ...pageRequest } as any
if (libraryId) {
Expand All @@ -20,6 +20,9 @@ export default class KomgaSeriesService {
if (search) {
params.search = search
}
if (status) {
params.status = status
}
return (await this.http.get(API_SERIES, {
params: params,
paramsSerializer: params => qs.stringify(params, { indices: false })
Expand Down
7 changes: 7 additions & 0 deletions komga-webui/src/types/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,10 @@ export enum MediaStatus {
Error = 'ERROR',
Unsupported = 'UNSUPPORTED'
}

export enum SeriesStatus {
ENDED = 'ENDED',
ONGOING = 'ONGOING',
ABANDONED = 'ABANDONED',
HIATUS = 'HIATUS'
}

0 comments on commit c540e56

Please sign in to comment.