mirror of
https://github.com/gotson/komga.git
synced 2025-12-20 07:23:34 +01:00
parent
494bdf28a1
commit
c3a3fa343b
7 changed files with 63 additions and 29 deletions
|
|
@ -6,10 +6,13 @@
|
|||
<v-subheader v-if="f.name">{{ f.name }}</v-subheader>
|
||||
<v-list-item v-for="v in f.values"
|
||||
:key="v.value"
|
||||
@click.stop="click(key, v.value)"
|
||||
@click.stop="click(key, v.value, v.nValue)"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
<v-icon v-if="key in filtersActive && filtersActive[key].includes(v.value)" color="secondary">
|
||||
<v-icon v-if="key in filtersActive && filtersActive[key].includes(v.nValue)" color="secondary">
|
||||
mdi-minus-box
|
||||
</v-icon>
|
||||
<v-icon v-else-if="key in filtersActive && filtersActive[key].includes(v.value)" color="secondary">
|
||||
mdi-checkbox-marked
|
||||
</v-icon>
|
||||
<v-icon v-else>
|
||||
|
|
@ -38,11 +41,16 @@ export default Vue.extend({
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
click (key: string, value: string) {
|
||||
click(key: string, value: string, nValue?: string) {
|
||||
let r = this.$_.cloneDeep(this.filtersActive)
|
||||
if (!(key in r)) r[key] = []
|
||||
if (r[key].includes(value)) this.$_.pull(r[key], (value))
|
||||
else r[key].push(value)
|
||||
if (nValue && r[key].includes(nValue))
|
||||
this.$_.pull(r[key], (nValue))
|
||||
else if (r[key].includes(value)) {
|
||||
this.$_.pull(r[key], (value))
|
||||
if (nValue)
|
||||
r[key].push(nValue)
|
||||
} else r[key].push(value)
|
||||
|
||||
this.$emit('update:filtersActive', r)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
const sortDirs = ['asc', 'desc']
|
||||
|
||||
export function parseQuerySort (querySort: any, sortOptions: SortOption[]): SortActive | null {
|
||||
export function parseQuerySort(querySort: any, sortOptions: SortOption[]): SortActive | null {
|
||||
let customSort = null
|
||||
if (querySort) {
|
||||
const split = querySort.split(',')
|
||||
if (split.length === 2 && sortOptions.map(x => x.key).includes(split[0]) && sortDirs.includes(split[1])) {
|
||||
customSort = { key: split[0], order: split[1] }
|
||||
customSort = {key: split[0], order: split[1]}
|
||||
}
|
||||
}
|
||||
return customSort
|
||||
}
|
||||
|
||||
export function parseBooleanFilter(values?: string[]): boolean | undefined {
|
||||
if (!values || values.length === 0) return undefined
|
||||
if (values[0].trim().toLowerCase() === 'true') return true
|
||||
if (values[0].trim().toLowerCase() === 'false') return false
|
||||
return undefined
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,19 +9,19 @@ const API_COLLECTIONS = '/api/v1/collections'
|
|||
export default class KomgaCollectionsService {
|
||||
private http: AxiosInstance
|
||||
|
||||
constructor (http: AxiosInstance) {
|
||||
constructor(http: AxiosInstance) {
|
||||
this.http = http
|
||||
}
|
||||
|
||||
async getCollections (libraryIds?: string[], pageRequest?: PageRequest, search?: string): Promise<Page<CollectionDto>> {
|
||||
async getCollections(libraryIds?: string[], pageRequest?: PageRequest, search?: string): Promise<Page<CollectionDto>> {
|
||||
try {
|
||||
const params = { ...pageRequest } as any
|
||||
const params = {...pageRequest} as any
|
||||
if (libraryIds) params.library_id = libraryIds
|
||||
if (search) params.search = search
|
||||
|
||||
return (await this.http.get(API_COLLECTIONS, {
|
||||
params: params,
|
||||
paramsSerializer: params => qs.stringify(params, { indices: false }),
|
||||
paramsSerializer: params => qs.stringify(params, {indices: false}),
|
||||
})).data
|
||||
} catch (e) {
|
||||
let msg = 'An error occurred while trying to retrieve collections'
|
||||
|
|
@ -32,7 +32,7 @@ export default class KomgaCollectionsService {
|
|||
}
|
||||
}
|
||||
|
||||
async getOneCollection (collectionId: string): Promise<CollectionDto> {
|
||||
async getOneCollection(collectionId: string): Promise<CollectionDto> {
|
||||
try {
|
||||
return (await this.http.get(`${API_COLLECTIONS}/${collectionId}`)).data
|
||||
} catch (e) {
|
||||
|
|
@ -44,7 +44,7 @@ export default class KomgaCollectionsService {
|
|||
}
|
||||
}
|
||||
|
||||
async postCollection (collection: CollectionCreationDto): Promise<CollectionDto> {
|
||||
async postCollection(collection: CollectionCreationDto): Promise<CollectionDto> {
|
||||
try {
|
||||
return (await this.http.post(API_COLLECTIONS, collection)).data
|
||||
} catch (e) {
|
||||
|
|
@ -56,7 +56,7 @@ export default class KomgaCollectionsService {
|
|||
}
|
||||
}
|
||||
|
||||
async patchCollection (collectionId: string, collection: CollectionUpdateDto) {
|
||||
async patchCollection(collectionId: string, collection: CollectionUpdateDto) {
|
||||
try {
|
||||
await this.http.patch(`${API_COLLECTIONS}/${collectionId}`, collection)
|
||||
} catch (e) {
|
||||
|
|
@ -68,7 +68,7 @@ export default class KomgaCollectionsService {
|
|||
}
|
||||
}
|
||||
|
||||
async deleteCollection (collectionId: string) {
|
||||
async deleteCollection(collectionId: string) {
|
||||
try {
|
||||
await this.http.delete(`${API_COLLECTIONS}/${collectionId}`)
|
||||
} catch (e) {
|
||||
|
|
@ -80,12 +80,13 @@ export default class KomgaCollectionsService {
|
|||
}
|
||||
}
|
||||
|
||||
async getSeries (collectionId: string, pageRequest?: PageRequest,
|
||||
libraryId?: string[], status?: string[],
|
||||
readStatus?: string[], genre?: string[], tag?: string[], language?: string[],
|
||||
publisher?: string[], ageRating?: string[], releaseDate?: string[], authors?: AuthorDto[]): Promise<Page<SeriesDto>> {
|
||||
async getSeries(collectionId: string, pageRequest?: PageRequest,
|
||||
libraryId?: string[], status?: string[],
|
||||
readStatus?: string[], genre?: string[], tag?: string[], language?: string[],
|
||||
publisher?: string[], ageRating?: string[], releaseDate?: string[], authors?: AuthorDto[],
|
||||
complete?: boolean): Promise<Page<SeriesDto>> {
|
||||
try {
|
||||
const params = { ...pageRequest } as any
|
||||
const params = {...pageRequest} as any
|
||||
if (libraryId) params.library_id = libraryId
|
||||
if (status) params.status = status
|
||||
if (readStatus) params.read_status = readStatus
|
||||
|
|
@ -96,10 +97,11 @@ export default class KomgaCollectionsService {
|
|||
if (ageRating) params.age_rating = ageRating
|
||||
if (releaseDate) params.release_year = releaseDate
|
||||
if (authors) params.author = authors.map(a => `${a.name},${a.role}`)
|
||||
if (complete !== undefined) params.complete = complete
|
||||
|
||||
return (await this.http.get(`${API_COLLECTIONS}/${collectionId}/series`, {
|
||||
params: params,
|
||||
paramsSerializer: params => qs.stringify(params, { indices: false }),
|
||||
paramsSerializer: params => qs.stringify(params, {indices: false}),
|
||||
})).data
|
||||
} catch (e) {
|
||||
let msg = 'An error occurred while trying to retrieve series'
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default class KomgaSeriesService {
|
|||
async getSeries(libraryId?: string, pageRequest?: PageRequest, search?: string, status?: string[],
|
||||
readStatus?: string[], genre?: string[], tag?: string[], language?: string[],
|
||||
publisher?: string[], ageRating?: string[], releaseDate?: string[], authors?: AuthorDto[],
|
||||
searchRegex?: string): Promise<Page<SeriesDto>> {
|
||||
searchRegex?: string, complete?: boolean): Promise<Page<SeriesDto>> {
|
||||
try {
|
||||
const params = {...pageRequest} as any
|
||||
if (libraryId) params.library_id = libraryId
|
||||
|
|
@ -31,6 +31,7 @@ export default class KomgaSeriesService {
|
|||
if (ageRating) params.age_rating = ageRating
|
||||
if (releaseDate) params.release_year = releaseDate
|
||||
if (authors) params.author = authors.map(a => `${a.name},${a.role}`)
|
||||
if (complete !== undefined) params.complete = complete
|
||||
|
||||
return (await this.http.get(API_SERIES, {
|
||||
params: params,
|
||||
|
|
@ -47,7 +48,7 @@ export default class KomgaSeriesService {
|
|||
|
||||
async getAlphabeticalGroups(libraryId?: string, search?: string, status?: string[],
|
||||
readStatus?: string[], genre?: string[], tag?: string[], language?: string[],
|
||||
publisher?: string[], ageRating?: string[], releaseDate?: string[], authors?: AuthorDto[]): Promise<GroupCountDto[]> {
|
||||
publisher?: string[], ageRating?: string[], releaseDate?: string[], authors?: AuthorDto[], complete?: boolean): Promise<GroupCountDto[]> {
|
||||
try {
|
||||
const params = {} as any
|
||||
if (libraryId) params.library_id = libraryId
|
||||
|
|
@ -61,6 +62,7 @@ export default class KomgaSeriesService {
|
|||
if (ageRating) params.age_rating = ageRating
|
||||
if (releaseDate) params.release_year = releaseDate
|
||||
if (authors) params.author = authors.map(a => `${a.name},${a.role}`)
|
||||
if (complete !== undefined) params.complete = complete
|
||||
|
||||
return (await this.http.get(`${API_SERIES}/alphabetical-groups`, {
|
||||
params: params,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ interface FiltersOptions {
|
|||
interface NameValue {
|
||||
name: string,
|
||||
value: string,
|
||||
// an optional negative value
|
||||
nValue?: string,
|
||||
}
|
||||
|
||||
interface FiltersActive {
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ import {AuthorDto} from '@/types/komga-books'
|
|||
import {CollectionSseDto, ReadProgressSeriesSseDto, SeriesSseDto} from '@/types/komga-sse'
|
||||
import {throttle} from 'lodash'
|
||||
import {LibraryDto} from '@/types/komga-libraries'
|
||||
import {parseBooleanFilter} from '@/functions/query-params'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'BrowseCollection',
|
||||
|
|
@ -231,6 +232,9 @@ export default Vue.extend({
|
|||
{name: this.$t('filter.read').toString(), value: ReadStatus.READ},
|
||||
],
|
||||
},
|
||||
complete: {
|
||||
values: [{name: 'Complete', value: 'true', nValue: 'false'}],
|
||||
},
|
||||
} as FiltersOptions
|
||||
},
|
||||
filterOptionsPanel(): FiltersOptions {
|
||||
|
|
@ -303,7 +307,7 @@ export default Vue.extend({
|
|||
|
||||
// get filter from query params or local storage and validate with available filter values
|
||||
let activeFilters: any
|
||||
if (route.query.status || route.query.readStatus || route.query.genre || route.query.tag || route.query.language || route.query.ageRating || route.query.library || route.query.publisher || authorRoles.some(role => role in route.query)) {
|
||||
if (route.query.status || route.query.readStatus || route.query.genre || route.query.tag || route.query.language || route.query.ageRating || route.query.library || route.query.publisher || authorRoles.some(role => role in route.query) || route.query.complete) {
|
||||
activeFilters = {
|
||||
status: route.query.status || [],
|
||||
readStatus: route.query.readStatus || [],
|
||||
|
|
@ -314,6 +318,7 @@ export default Vue.extend({
|
|||
language: route.query.language || [],
|
||||
ageRating: route.query.ageRating || [],
|
||||
releaseDate: route.query.releaseDate || [],
|
||||
complete: route.query.complete || [],
|
||||
}
|
||||
authorRoles.forEach((role: string) => {
|
||||
activeFilters[role] = route.query[role] || []
|
||||
|
|
@ -334,6 +339,7 @@ export default Vue.extend({
|
|||
language: filters.language?.filter(x => this.filterOptions.language.map(n => n.value).includes(x)) || [],
|
||||
ageRating: filters.ageRating?.filter(x => this.filterOptions.ageRating.map(n => n.value).includes(x)) || [],
|
||||
releaseDate: filters.releaseDate?.filter(x => this.filterOptions.releaseDate.map(n => n.value).includes(x)) || [],
|
||||
complete: filters.complete?.filter(x => x === 'true' || x === 'false') || [],
|
||||
} as any
|
||||
authorRoles.forEach((role: string) => {
|
||||
validFilter[role] = filters[role] || []
|
||||
|
|
@ -379,7 +385,8 @@ export default Vue.extend({
|
|||
}))
|
||||
})
|
||||
|
||||
this.series = (await this.$komgaCollections.getSeries(collectionId, {unpaged: true} as PageRequest, this.filters.library, this.filters.status, replaceCompositeReadStatus(this.filters.readStatus), this.filters.genre, this.filters.tag, this.filters.language, this.filters.publisher, this.filters.ageRating, this.filters.releaseDate, authorsFilter)).content
|
||||
const complete = parseBooleanFilter(this.filters.complete)
|
||||
this.series = (await this.$komgaCollections.getSeries(collectionId, {unpaged: true} as PageRequest, this.filters.library, this.filters.status, replaceCompositeReadStatus(this.filters.readStatus), this.filters.genre, this.filters.tag, this.filters.language, this.filters.publisher, this.filters.ageRating, this.filters.releaseDate, authorsFilter, complete)).content
|
||||
this.seriesCopy = [...this.series]
|
||||
this.selectedSeries = []
|
||||
},
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ import ItemBrowser from '@/components/ItemBrowser.vue'
|
|||
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
||||
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
||||
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
||||
import {parseQuerySort} from '@/functions/query-params'
|
||||
import {parseBooleanFilter, parseQuerySort} from '@/functions/query-params'
|
||||
import {ReadStatus, replaceCompositeReadStatus} from '@/types/enum-books'
|
||||
import {SeriesStatus, SeriesStatusKeyValue} from '@/types/enum-series'
|
||||
import {
|
||||
|
|
@ -281,6 +281,9 @@ export default Vue.extend({
|
|||
{name: this.$t('filter.read').toString(), value: ReadStatus.READ},
|
||||
],
|
||||
},
|
||||
complete: {
|
||||
values: [{name: 'Complete', value: 'true', nValue: 'false'}],
|
||||
},
|
||||
} as FiltersOptions
|
||||
},
|
||||
filterOptionsPanel(): FiltersOptions {
|
||||
|
|
@ -377,7 +380,7 @@ export default Vue.extend({
|
|||
|
||||
// get filter from query params or local storage and validate with available filter values
|
||||
let activeFilters: any
|
||||
if (route.query.status || route.query.readStatus || route.query.genre || route.query.tag || route.query.language || route.query.ageRating || route.query.publisher || authorRoles.some(role => role in route.query)) {
|
||||
if (route.query.status || route.query.readStatus || route.query.genre || route.query.tag || route.query.language || route.query.ageRating || route.query.publisher || authorRoles.some(role => role in route.query) || route.query.complete) {
|
||||
activeFilters = {
|
||||
status: route.query.status || [],
|
||||
readStatus: route.query.readStatus || [],
|
||||
|
|
@ -387,6 +390,7 @@ export default Vue.extend({
|
|||
language: route.query.language || [],
|
||||
ageRating: route.query.ageRating || [],
|
||||
releaseDate: route.query.releaseDate || [],
|
||||
complete: route.query.complete || [],
|
||||
}
|
||||
authorRoles.forEach((role: string) => {
|
||||
activeFilters[role] = route.query[role] || []
|
||||
|
|
@ -406,6 +410,7 @@ export default Vue.extend({
|
|||
language: filters.language?.filter(x => this.filterOptions.language.map(n => n.value).includes(x)) || [],
|
||||
ageRating: filters.ageRating?.filter(x => this.filterOptions.ageRating.map(n => n.value).includes(x)) || [],
|
||||
releaseDate: filters.releaseDate?.filter(x => this.filterOptions.releaseDate.map(n => n.value).includes(x)) || [],
|
||||
complete: filters.complete?.filter(x => x === 'true' || x === 'false') || [],
|
||||
} as any
|
||||
authorRoles.forEach((role: string) => {
|
||||
validFilter[role] = filters[role] || []
|
||||
|
|
@ -510,13 +515,14 @@ export default Vue.extend({
|
|||
})
|
||||
|
||||
const requestLibraryId = libraryId !== LIBRARIES_ALL ? libraryId : undefined
|
||||
const seriesPage = await this.$komgaSeries.getSeries(requestLibraryId, pageRequest, undefined, this.filters.status, replaceCompositeReadStatus(this.filters.readStatus), this.filters.genre, this.filters.tag, this.filters.language, this.filters.publisher, this.filters.ageRating, this.filters.releaseDate, authorsFilter, searchRegex)
|
||||
const complete = parseBooleanFilter(this.filters.complete)
|
||||
const seriesPage = await this.$komgaSeries.getSeries(requestLibraryId, pageRequest, undefined, this.filters.status, replaceCompositeReadStatus(this.filters.readStatus), this.filters.genre, this.filters.tag, this.filters.language, this.filters.publisher, this.filters.ageRating, this.filters.releaseDate, authorsFilter, searchRegex, complete)
|
||||
|
||||
this.totalPages = seriesPage.totalPages
|
||||
this.totalElements = seriesPage.totalElements
|
||||
this.series = seriesPage.content
|
||||
|
||||
const seriesGroups = await this.$komgaSeries.getAlphabeticalGroups(requestLibraryId, undefined, this.filters.status, replaceCompositeReadStatus(this.filters.readStatus), this.filters.genre, this.filters.tag, this.filters.language, this.filters.publisher, this.filters.ageRating, this.filters.releaseDate, authorsFilter)
|
||||
const seriesGroups = await this.$komgaSeries.getAlphabeticalGroups(requestLibraryId, undefined, this.filters.status, replaceCompositeReadStatus(this.filters.readStatus), this.filters.genre, this.filters.tag, this.filters.language, this.filters.publisher, this.filters.ageRating, this.filters.releaseDate, authorsFilter, complete)
|
||||
const nonAlpha = seriesGroups
|
||||
.filter((g) => !(/[a-zA-Z]/).test(g.group))
|
||||
.reduce((a, b) => a + b.count, 0)
|
||||
|
|
|
|||
Loading…
Reference in a new issue