Skip to content

Commit

Permalink
feat(webui): add read status filter when browsing Series
Browse files Browse the repository at this point in the history
related to gotson#25
  • Loading branch information
gotson committed Jun 5, 2020
1 parent fc5c502 commit cc39ce8
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 21 deletions.
94 changes: 94 additions & 0 deletions komga-webui/src/components/FilterMenuButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<template>
<v-menu offset-y>
<template v-slot:activator="{on}">
<v-btn icon v-on="on">
<v-icon :color="filterCustom ? 'secondary' : null"
>mdi-filter-variant
</v-icon>
</v-btn>
</template>
<v-list>
<div v-for="(f, i) in filtersOptions"
:key="i"
>
<v-subheader>{{ f.name }}</v-subheader>
<v-list-item v-for="v in f.values"
:key="v"
@click.stop="click(i, v)"
>
<v-list-item-icon>
<v-icon v-if="filtersActive[i].includes(v)" color="secondary">
mdi-checkbox-marked
</v-icon>
<v-icon v-else>
mdi-checkbox-blank-outline
</v-icon>
</v-list-item-icon>
<v-list-item-title class="text-capitalize">
{{ v.toString().toLowerCase().replace('_', ' ') }}
</v-list-item-title>
</v-list-item>
</div>

<v-list-item v-if="filterCustom"
@click="clearAll()"
dense
>
<v-list-item-icon>
<v-icon>mdi-close</v-icon>
</v-list-item-icon>
<v-list-item-title>Clear</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</template>

<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
name: 'FilterMenuButton',
props: {
// array of object: name, values[]
filtersOptions: {
type: Array,
required: true,
},
// array of arrays containing the selection, use with sync
filtersActive: {
type: Array,
required: true,
},
},
computed: {
filterCustom (): boolean {
let r = false
this.filtersActive.forEach(x => {
if (!this.$_.isEmpty(x)) r = true
})
return r
},
},
methods: {
clearAll () {
let r = [] as any[]
this.$_.times(this.filtersActive.length, x => {
r.push([])
})
this.$emit('update:filtersActive', r)
},
click (index: number, value: string) {
let r = this.$_.cloneDeep(this.filtersActive) as any[]
if (r[index].includes(value)) this.$_.pull(r[index], (value))
else r[index].push(value)
this.$emit('update:filtersActive', r)
},
},
})
</script>

<style scoped>
</style>
8 changes: 6 additions & 2 deletions komga-webui/src/services/komga-series.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,14 @@ export default class KomgaSeriesService {
}
}

async getBooks (seriesId: number, pageRequest?: PageRequest): Promise<Page<BookDto>> {
async getBooks (seriesId: number, pageRequest?: PageRequest, readStatus?: string[]): Promise<Page<BookDto>> {
try {
const params = { ...pageRequest } as any
if (readStatus) {
params.read_status = readStatus
}
return (await this.http.get(`${API_SERIES}/${seriesId}/books`, {
params: { ...pageRequest },
params: params,
paramsSerializer: params => qs.stringify(params, { indices: false }),
})).data
} catch (e) {
Expand Down
4 changes: 2 additions & 2 deletions komga-webui/src/types/enum-books.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ export enum MediaStatus {

export enum ReadStatus {
UNREAD = 'UNREAD',
READ = 'READ',
IN_PROGRESS = 'IN_PROGRESS'
IN_PROGRESS = 'IN_PROGRESS',
READ = 'READ'
}
46 changes: 39 additions & 7 deletions komga-webui/src/views/BrowseSeries.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
<v-icon>mdi-pencil</v-icon>
</v-btn>

<!-- Filter menu -->
<filter-menu-button :filters-options="filterOptions"
:filters-active.sync="filters"
/>

<!-- Sort menu -->
<sort-menu-button :sort-default="sortDefault"
:sort-options="sortOptions"
Expand Down Expand Up @@ -128,13 +133,24 @@

<v-divider class="my-4"/>

<v-pagination
v-model="page"
:total-visible="paginationVisible"
:length="totalPages"
/>
<empty-state
v-if="totalPages === 0"
title="The active filter has no matches"
sub-title="Use the menu above to change the active filter"
icon="mdi-book-multiple"
icon-color="secondary"
>
</empty-state>

<template v-else>
<v-pagination
v-model="page"
:total-visible="paginationVisible"
:length="totalPages"
/>

<item-browser :items="books" :selected.sync="selected" :edit-function="this.singleEdit" class="px-4"/>
<item-browser :items="books" :selected.sync="selected" :edit-function="this.singleEdit" class="px-4"/>
</template>

</v-container>

Expand All @@ -146,13 +162,16 @@
import Badge from '@/components/Badge.vue'
import EditBooksDialog from '@/components/EditBooksDialog.vue'
import EditSeriesDialog from '@/components/EditSeriesDialog.vue'
import EmptyState from '@/components/EmptyState.vue'
import FilterMenuButton from '@/components/FilterMenuButton.vue'
import ItemBrowser from '@/components/ItemBrowser.vue'
import ItemCard from '@/components/ItemCard.vue'
import PageSizeSelect from '@/components/PageSizeSelect.vue'
import SortMenuButton from '@/components/SortMenuButton.vue'
import ToolbarSticky from '@/components/ToolbarSticky.vue'
import { parseQuerySort } from '@/functions/query-params'
import { seriesThumbnailUrl } from '@/functions/urls'
import { ReadStatus } from '@/types/enum-books'
import Vue from 'vue'
const cookiePageSize = 'pagesize'
Expand All @@ -162,12 +181,14 @@ export default Vue.extend({
components: {
ToolbarSticky,
SortMenuButton,
FilterMenuButton,
Badge,
EditSeriesDialog,
EditBooksDialog,
ItemBrowser,
PageSizeSelect,
ItemCard,
EmptyState,
},
data: () => {
return {
Expand All @@ -185,8 +206,11 @@ export default Vue.extend({
}] as SortOption[],
sortActive: {} as SortActive,
sortDefault: { key: 'metadata.numberSort', order: 'asc' } as SortActive,
filterOptions: [{ name: 'READ STATUS', values: ReadStatus }],
filters: [[]] as any[],
dialogEdit: false,
sortUnwatch: null as any,
filterUnwatch: null as any,
pageUnwatch: null as any,
pageSizeUnwatch: null as any,
selected: [],
Expand Down Expand Up @@ -253,6 +277,7 @@ export default Vue.extend({
// restore from query param
this.sortActive = this.parseQuerySortOrDefault(this.$route.query.sort)
this.filters.splice(0, 1, this.parseQueryFilterStatus(this.$route.query.readStatus))
if (this.$route.query.page) this.page = Number(this.$route.query.page)
if (this.$route.query.pageSize) this.pageSize = Number(this.$route.query.pageSize)
Expand All @@ -266,6 +291,7 @@ export default Vue.extend({
// reset
this.sortActive = this.parseQuerySortOrDefault(to.query.sort)
this.filters.splice(0, 1, this.parseQueryFilterStatus(to.query.readStatus))
this.page = 1
this.totalPages = 1
this.totalElements = null
Expand All @@ -281,6 +307,7 @@ export default Vue.extend({
methods: {
setWatches () {
this.sortUnwatch = this.$watch('sortActive', this.updateRouteAndReload)
this.filterUnwatch = this.$watch('filters', this.updateRouteAndReload)
this.pageSizeUnwatch = this.$watch('pageSize', (val) => {
this.$cookies.set(cookiePageSize, val, Infinity)
this.updateRouteAndReload()
Expand All @@ -293,6 +320,7 @@ export default Vue.extend({
},
unsetWatches () {
this.sortUnwatch()
this.filterUnwatch()
this.pageUnwatch()
this.pageSizeUnwatch()
},
Expand All @@ -314,6 +342,9 @@ export default Vue.extend({
parseQuerySortOrDefault (querySort: any): SortActive {
return parseQuerySort(querySort, this.sortOptions) || this.$_.clone(this.sortDefault)
},
parseQueryFilterStatus (queryStatus: any): string[] {
return queryStatus ? queryStatus.toString().split(',').filter((x: string) => Object.keys(ReadStatus).includes(x)) : []
},
updateRoute (index?: string) {
this.$router.replace({
name: this.$route.name,
Expand All @@ -322,6 +353,7 @@ export default Vue.extend({
page: `${this.page}`,
pageSize: `${this.pageSize}`,
sort: `${this.sortActive.key},${this.sortActive.order}`,
readStatus: `${this.filters[0]}`,
},
}).catch(_ => {
})
Expand All @@ -335,7 +367,7 @@ export default Vue.extend({
if (sort) {
pageRequest.sort = [`${sort.key},${sort.order}`]
}
const booksPage = await this.$komgaSeries.getBooks(seriesId, pageRequest)
const booksPage = await this.$komgaSeries.getBooks(seriesId, pageRequest, this.filters[0])
this.totalPages = booksPage.totalPages
this.totalElements = booksPage.totalElements
Expand Down
14 changes: 4 additions & 10 deletions komga-webui/src/views/Dashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
>
</empty-state>

<horizontal-scroller v-if="inProgressBooks.length !== 0">
<horizontal-scroller v-if="inProgressBooks.length !== 0" class="my-4">
<template v-slot:prepend>
<div class="title">Keep Reading</div>
</template>
Expand All @@ -29,9 +29,7 @@
</template>
</horizontal-scroller>

<br>

<horizontal-scroller v-if="newSeries.length !== 0">
<horizontal-scroller v-if="newSeries.length !== 0" class="my-4">
<template v-slot:prepend>
<div class="title">Recently Added Series</div>
</template>
Expand All @@ -43,9 +41,7 @@
</template>
</horizontal-scroller>

<br>

<horizontal-scroller v-if="updatedSeries.length !== 0">
<horizontal-scroller v-if="updatedSeries.length !== 0" class="my-4">
<template v-slot:prepend>
<div class="title">Recently Updated Series</div>
</template>
Expand All @@ -57,9 +53,7 @@
</template>
</horizontal-scroller>

<br>

<horizontal-scroller v-if="latestBooks.length !== 0">
<horizontal-scroller v-if="latestBooks.length !== 0" class="my-4">
<template v-slot:prepend>
<div class="title">Recently Added Books</div>
</template>
Expand Down

0 comments on commit cc39ce8

Please sign in to comment.