mirror of
https://github.com/gotson/komga.git
synced 2025-12-20 15:34:17 +01:00
fix(webui): query param doesn't work with values containing comma
closes #557
This commit is contained in:
parent
7d7fbad749
commit
b447101bcc
7 changed files with 48 additions and 48 deletions
|
|
@ -6,7 +6,7 @@ export function sortOrFilterActive (sortActive: SortActive, sortDefault: SortAct
|
||||||
|
|
||||||
export function mergeFilterParams (filter: FiltersActive, query: any) {
|
export function mergeFilterParams (filter: FiltersActive, query: any) {
|
||||||
for (const f of Object.keys(filter)) {
|
for (const f of Object.keys(filter)) {
|
||||||
if (filter[f].length !== 0) query[f] = `${filter[f]}`
|
if (filter[f].length !== 0) query[f] = filter[f]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,3 @@ export function parseQuerySort (querySort: any, sortOptions: SortOption[]): Sort
|
||||||
}
|
}
|
||||||
return customSort
|
return customSort
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseQueryParamAndFilter (queryParam: any, enumeration: string[]): string[] {
|
|
||||||
return queryParam ? queryParam.toString().split(',').filter((x: string) => enumeration.includes(x)) : []
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseQueryParam (queryParam: any): string[] {
|
|
||||||
return queryParam ? queryParam.toString().split(',') : []
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ import urls from '@/functions/urls'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Router from 'vue-router'
|
import Router from 'vue-router'
|
||||||
import store from './store'
|
import store from './store'
|
||||||
import {LIBRARIES_ALL, LIBRARY_ROUTE} from "@/types/library";
|
import {LIBRARIES_ALL, LIBRARY_ROUTE} from "@/types/library"
|
||||||
|
|
||||||
|
const qs = require('qs')
|
||||||
|
|
||||||
Vue.use(Router)
|
Vue.use(Router)
|
||||||
|
|
||||||
|
|
@ -36,6 +38,13 @@ const getLibraryRoute = (libraryId: string) => {
|
||||||
const router = new Router({
|
const router = new Router({
|
||||||
mode: 'history',
|
mode: 'history',
|
||||||
base: urls.base,
|
base: urls.base,
|
||||||
|
parseQuery(query: string) {
|
||||||
|
return qs.parse(query)
|
||||||
|
},
|
||||||
|
stringifyQuery(query: Object) {
|
||||||
|
const res = qs.stringify(query)
|
||||||
|
return res ? `?${res}` : ''
|
||||||
|
},
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,7 @@
|
||||||
:key="i"
|
:key="i"
|
||||||
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
|
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
|
||||||
:title="name"
|
:title="name"
|
||||||
:to="{name:'browse-series', params: {seriesId: book.seriesId }, query: {[role]: name}}"
|
:to="{name:'browse-series', params: {seriesId: book.seriesId }, query: {[role]: [name]}}"
|
||||||
label
|
label
|
||||||
small
|
small
|
||||||
outlined
|
outlined
|
||||||
|
|
@ -265,7 +265,7 @@
|
||||||
:key="i"
|
:key="i"
|
||||||
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
|
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
|
||||||
:title="t"
|
:title="t"
|
||||||
:to="{name:'browse-series', params: {seriesId: book.seriesId}, query: {tag: t}}"
|
:to="{name:'browse-series', params: {seriesId: book.seriesId}, query: {tag: [t]}}"
|
||||||
label
|
label
|
||||||
small
|
small
|
||||||
outlined
|
outlined
|
||||||
|
|
|
||||||
|
|
@ -126,11 +126,10 @@ import FilterPanels from '@/components/FilterPanels.vue'
|
||||||
import FilterList from '@/components/FilterList.vue'
|
import FilterList from '@/components/FilterList.vue'
|
||||||
import {Location} from 'vue-router'
|
import {Location} from 'vue-router'
|
||||||
import EmptyState from '@/components/EmptyState.vue'
|
import EmptyState from '@/components/EmptyState.vue'
|
||||||
import {parseQueryParam} from '@/functions/query-params'
|
import {SeriesDto} from "@/types/komga-series"
|
||||||
import {SeriesDto} from "@/types/komga-series";
|
import {authorRoles} from "@/types/author-roles"
|
||||||
import {authorRoles} from "@/types/author-roles";
|
import {AuthorDto} from "@/types/komga-books"
|
||||||
import {AuthorDto} from "@/types/komga-books";
|
import {CollectionSseDto, SeriesSseDto} from "@/types/komga-sse"
|
||||||
import {CollectionSseDto, SeriesSseDto} from "@/types/komga-sse";
|
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'BrowseCollection',
|
name: 'BrowseCollection',
|
||||||
|
|
@ -304,18 +303,18 @@ export default Vue.extend({
|
||||||
let activeFilters: any
|
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)) {
|
||||||
activeFilters = {
|
activeFilters = {
|
||||||
status: parseQueryParam(route.query.status),
|
status: route.query.status || [],
|
||||||
readStatus: parseQueryParam(route.query.readStatus),
|
readStatus: route.query.readStatus || [],
|
||||||
library: parseQueryParam(route.query.library),
|
library: route.query.library || [],
|
||||||
genre: parseQueryParam(route.query.genre),
|
genre: route.query.genre || [],
|
||||||
tag: parseQueryParam(route.query.tag),
|
tag: route.query.tag || [],
|
||||||
publisher: parseQueryParam(route.query.publisher),
|
publisher: route.query.publisher || [],
|
||||||
language: parseQueryParam(route.query.language),
|
language: route.query.language || [],
|
||||||
ageRating: parseQueryParam(route.query.ageRating),
|
ageRating: route.query.ageRating || [],
|
||||||
releaseDate: parseQueryParam(route.query.releaseDate),
|
releaseDate: route.query.releaseDate || [],
|
||||||
}
|
}
|
||||||
authorRoles.forEach((role: string) => {
|
authorRoles.forEach((role: string) => {
|
||||||
activeFilters[role] = parseQueryParam(route.query[role])
|
activeFilters[role] = route.query[role] || []
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
activeFilters = this.$store.getters.getCollectionFilter(route.params.collectionId) || {} as FiltersActive
|
activeFilters = this.$store.getters.getCollectionFilter(route.params.collectionId) || {} as FiltersActive
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||||
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
||||||
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
||||||
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
||||||
import {parseQueryParam, parseQuerySort} from '@/functions/query-params'
|
import {parseQuerySort} from '@/functions/query-params'
|
||||||
import {ReadStatus, replaceCompositeReadStatus} from '@/types/enum-books'
|
import {ReadStatus, replaceCompositeReadStatus} from '@/types/enum-books'
|
||||||
import {SeriesStatus, SeriesStatusKeyValue} from '@/types/enum-series'
|
import {SeriesStatus, SeriesStatusKeyValue} from '@/types/enum-series'
|
||||||
import {LIBRARY_CHANGED, LIBRARY_DELETED, SERIES_ADDED, SERIES_CHANGED, SERIES_DELETED} from '@/types/events'
|
import {LIBRARY_CHANGED, LIBRARY_DELETED, SERIES_ADDED, SERIES_CHANGED, SERIES_DELETED} from '@/types/events'
|
||||||
|
|
@ -337,17 +337,17 @@ export default Vue.extend({
|
||||||
let activeFilters: any
|
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)) {
|
||||||
activeFilters = {
|
activeFilters = {
|
||||||
status: parseQueryParam(route.query.status),
|
status: route.query.status || [],
|
||||||
readStatus: parseQueryParam(route.query.readStatus),
|
readStatus: route.query.readStatus || [],
|
||||||
genre: parseQueryParam(route.query.genre),
|
genre: route.query.genre || [],
|
||||||
tag: parseQueryParam(route.query.tag),
|
tag: route.query.tag || [],
|
||||||
publisher: parseQueryParam(route.query.publisher),
|
publisher: route.query.publisher || [],
|
||||||
language: parseQueryParam(route.query.language),
|
language: route.query.language || [],
|
||||||
ageRating: parseQueryParam(route.query.ageRating),
|
ageRating: route.query.ageRating || [],
|
||||||
releaseDate: parseQueryParam(route.query.releaseDate),
|
releaseDate: route.query.releaseDate || [],
|
||||||
}
|
}
|
||||||
authorRoles.forEach((role: string) => {
|
authorRoles.forEach((role: string) => {
|
||||||
activeFilters[role] = parseQueryParam(route.query[role])
|
activeFilters[role] = route.query[role] || []
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
activeFilters = this.$store.getters.getLibraryFilter(route.params.libraryId) || {} as FiltersActive
|
activeFilters = this.$store.getters.getLibraryFilter(route.params.libraryId) || {} as FiltersActive
|
||||||
|
|
|
||||||
|
|
@ -112,20 +112,20 @@
|
||||||
<v-row class="text-body-2">
|
<v-row class="text-body-2">
|
||||||
<v-col :class="'py-1 ' + ($vuetify.rtl ? 'pl-0' : 'pr-0')" cols="auto">
|
<v-col :class="'py-1 ' + ($vuetify.rtl ? 'pl-0' : 'pr-0')" cols="auto">
|
||||||
<v-chip label small link :color="statusChip.color" :text-color="statusChip.text"
|
<v-chip label small link :color="statusChip.color" :text-color="statusChip.text"
|
||||||
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {status: series.metadata.status}}">
|
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {status: [series.metadata.status]}}">
|
||||||
{{ $t(`enums.series_status.${series.metadata.status}`) }}
|
{{ $t(`enums.series_status.${series.metadata.status}`) }}
|
||||||
</v-chip>
|
</v-chip>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col :class="'py-1 ' + ($vuetify.rtl ? 'pl-0' : 'pr-0')" cols="auto">
|
<v-col :class="'py-1 ' + ($vuetify.rtl ? 'pl-0' : 'pr-0')" cols="auto">
|
||||||
<v-chip label small link v-if="series.metadata.ageRating"
|
<v-chip label small link v-if="series.metadata.ageRating"
|
||||||
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {ageRating: series.metadata.ageRating}}"
|
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {ageRating: [series.metadata.ageRating]}}"
|
||||||
>
|
>
|
||||||
{{ series.metadata.ageRating }}+
|
{{ series.metadata.ageRating }}+
|
||||||
</v-chip>
|
</v-chip>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col :class="'py-1 ' + ($vuetify.rtl ? 'pl-0' : 'pr-0')" cols="auto">
|
<v-col :class="'py-1 ' + ($vuetify.rtl ? 'pl-0' : 'pr-0')" cols="auto">
|
||||||
<v-chip label small link
|
<v-chip label small link
|
||||||
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {language: series.metadata.language}}"
|
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {language: [series.metadata.language]}}"
|
||||||
v-if="series.metadata.language"
|
v-if="series.metadata.language"
|
||||||
>
|
>
|
||||||
{{ languageDisplay }}
|
{{ languageDisplay }}
|
||||||
|
|
@ -219,7 +219,7 @@
|
||||||
<v-chip
|
<v-chip
|
||||||
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
|
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
|
||||||
:title="series.metadata.publisher"
|
:title="series.metadata.publisher"
|
||||||
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {publisher: series.metadata.publisher}}"
|
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {publisher: [series.metadata.publisher]}}"
|
||||||
label
|
label
|
||||||
small
|
small
|
||||||
outlined
|
outlined
|
||||||
|
|
@ -249,7 +249,7 @@
|
||||||
:key="i"
|
:key="i"
|
||||||
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
|
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
|
||||||
:title="t"
|
:title="t"
|
||||||
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {genre: t}}"
|
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {genre: [t]}}"
|
||||||
label
|
label
|
||||||
small
|
small
|
||||||
outlined
|
outlined
|
||||||
|
|
@ -280,7 +280,7 @@
|
||||||
:key="i"
|
:key="i"
|
||||||
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
|
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
|
||||||
:title="t"
|
:title="t"
|
||||||
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {tag: t}}"
|
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {tag: [t]}}"
|
||||||
label
|
label
|
||||||
small
|
small
|
||||||
outlined
|
outlined
|
||||||
|
|
@ -315,7 +315,7 @@
|
||||||
:key="i"
|
:key="i"
|
||||||
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
|
:class="$vuetify.rtl ? 'ml-2' : 'mr-2'"
|
||||||
:title="name"
|
:title="name"
|
||||||
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {[role]: name}}"
|
:to="{name:'browse-libraries', params: {libraryId: series.libraryId }, query: {[role]: [name]}}"
|
||||||
label
|
label
|
||||||
small
|
small
|
||||||
outlined
|
outlined
|
||||||
|
|
@ -378,7 +378,7 @@ import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||||
import ItemCard from '@/components/ItemCard.vue'
|
import ItemCard from '@/components/ItemCard.vue'
|
||||||
import SeriesActionsMenu from '@/components/menus/SeriesActionsMenu.vue'
|
import SeriesActionsMenu from '@/components/menus/SeriesActionsMenu.vue'
|
||||||
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
||||||
import {parseQueryParam, parseQueryParamAndFilter, parseQuerySort} from '@/functions/query-params'
|
import {parseQuerySort} from '@/functions/query-params'
|
||||||
import {seriesFileUrl, seriesThumbnailUrl} from '@/functions/urls'
|
import {seriesFileUrl, seriesThumbnailUrl} from '@/functions/urls'
|
||||||
import {ReadStatus, replaceCompositeReadStatus} from '@/types/enum-books'
|
import {ReadStatus, replaceCompositeReadStatus} from '@/types/enum-books'
|
||||||
import {
|
import {
|
||||||
|
|
@ -628,11 +628,11 @@ export default Vue.extend({
|
||||||
this.$set(this.filterOptions, 'tag', toNameValue(await this.$komgaReferential.getBookTags(seriesId)))
|
this.$set(this.filterOptions, 'tag', toNameValue(await this.$komgaReferential.getBookTags(seriesId)))
|
||||||
|
|
||||||
// filter query params with available filter values
|
// filter query params with available filter values
|
||||||
this.$set(this.filters, 'readStatus', parseQueryParamAndFilter(this.$route.query.readStatus, Object.keys(ReadStatus)))
|
this.$set(this.filters, 'readStatus', (route.query.readStatus || []).filter((x: string) => Object.keys(ReadStatus).includes(x)))
|
||||||
this.$set(this.filters, 'tag', parseQueryParamAndFilter(this.$route.query.tag, this.filterOptions.tag.map(x => x.value)))
|
this.$set(this.filters, 'tag', (route.query.tag || []).filter((x: string) => this.filterOptions.tag.map(x => x.value).includes(x)))
|
||||||
authorRoles.forEach((role: string) => {
|
authorRoles.forEach((role: string) => {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
this.$set(this.filters, role, parseQueryParam(route.query[role]))
|
this.$set(this.filters, role, route.query[role] || [])
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setWatches() {
|
setWatches() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue