mirror of
https://github.com/gotson/komga.git
synced 2025-12-06 08:32:25 +01:00
feat(webui): add unavailable condition in series and books filters
Closes: #1580
This commit is contained in:
parent
87d73cc207
commit
1b8fa45ef2
5 changed files with 54 additions and 4 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import {SearchConditionSeries} from '@/types/komga-search'
|
||||
import {FiltersActive, NameValue} from '@/types/filter'
|
||||
|
||||
export function sortOrFilterActive(sortActive: SortActive, sortDefault: SortActive, filters: FiltersActive): boolean {
|
||||
const sortCustom = sortActive.key !== sortDefault.key || sortActive.order !== sortDefault.order
|
||||
|
|
|
|||
|
|
@ -190,6 +190,14 @@ export class SearchConditionTitleSort implements SearchConditionSeries {
|
|||
}
|
||||
}
|
||||
|
||||
export class SearchConditionDeleted implements SearchConditionBook, SearchConditionSeries {
|
||||
deleted: SearchOperatorBoolean
|
||||
|
||||
constructor(op: SearchOperatorBoolean) {
|
||||
this.deleted = op
|
||||
}
|
||||
}
|
||||
|
||||
export interface AuthorMatch {
|
||||
name?: string,
|
||||
role?: string
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ import {
|
|||
SearchConditionAllOfBook,
|
||||
SearchConditionAnyOfBook,
|
||||
SearchConditionAuthor,
|
||||
SearchConditionDeleted,
|
||||
SearchConditionLibraryId,
|
||||
SearchConditionMediaProfile,
|
||||
SearchConditionOneShot,
|
||||
|
|
@ -348,6 +349,15 @@ export default Vue.extend({
|
|||
nValue: new SearchConditionOneShot(new SearchOperatorIsFalse()),
|
||||
}],
|
||||
},
|
||||
deleted: {
|
||||
values: [
|
||||
{
|
||||
name: this.$t('common.unavailable').toString(),
|
||||
value: new SearchConditionDeleted(new SearchOperatorIsTrue()),
|
||||
nValue: new SearchConditionDeleted(new SearchOperatorIsFalse()),
|
||||
},
|
||||
],
|
||||
},
|
||||
} as FiltersOptions
|
||||
},
|
||||
filterOptionsPanel(): FiltersOptions {
|
||||
|
|
@ -436,11 +446,12 @@ export default Vue.extend({
|
|||
|
||||
// get filter from query params or local storage and validate with available filter values
|
||||
let activeFilters: any
|
||||
if (route.query.readStatus || route.query.tag || authorRoles.some(role => role in route.query) || route.query.oneshot) {
|
||||
if (route.query.readStatus || route.query.tag || authorRoles.some(role => role in route.query) || route.query.oneshot || route.query.deleted) {
|
||||
activeFilters = {
|
||||
readStatus: route.query.readStatus || [],
|
||||
tag: route.query.tag || [],
|
||||
oneshot: route.query.oneshot || [],
|
||||
deleted: route.query.deleted || [],
|
||||
}
|
||||
authorRoles.forEach((role: string) => {
|
||||
activeFilters[role] = route.query[role] || []
|
||||
|
|
@ -471,6 +482,7 @@ export default Vue.extend({
|
|||
readStatus: this.$_.intersectionWith(filters.readStatus, extractFilterOptionsValues(this.filterOptionsList.readStatus.values), objIsEqual) || [],
|
||||
tag: this.$_.intersectionWith(filters.tag, extractFilterOptionsValues(this.filterOptions.tag), objIsEqual) || [],
|
||||
oneshot: this.$_.intersectionWith(filters.oneshot, extractFilterOptionsValues(this.filterOptionsList.oneshot.values), objIsEqual) || [],
|
||||
deleted: this.$_.intersectionWith(filters.deleted, extractFilterOptionsValues(this.filterOptionsList.deleted.values), objIsEqual) || [],
|
||||
} as any
|
||||
authorRoles.forEach((role: string) => {
|
||||
validFilter[role] = filters[role] || []
|
||||
|
|
@ -581,6 +593,7 @@ export default Vue.extend({
|
|||
if (this.filters.tag && this.filters.tag.length > 0) this.filtersMode?.tag?.allOf ? conditions.push(new SearchConditionAllOfBook(this.filters.tag)) : conditions.push(new SearchConditionAnyOfBook(this.filters.tag))
|
||||
if (this.filters.oneshot && this.filters.oneshot.length > 0) conditions.push(...this.filters.oneshot)
|
||||
if (this.filters.mediaProfile && this.filters.mediaProfile.length > 0) this.filtersMode?.mediaProfile?.allOf ? conditions.push(new SearchConditionAllOfBook(this.filters.mediaProfile)) : conditions.push(new SearchConditionAnyOfBook(this.filters.mediaProfile))
|
||||
if (this.filters.deleted && this.filters.deleted.length > 0) conditions.push(...this.filters.deleted)
|
||||
authorRoles.forEach((role: string) => {
|
||||
if (role in this.filters) {
|
||||
const authorConditions = this.filters[role].map((name: string) => {
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ import {
|
|||
SearchConditionAnyOfSeries,
|
||||
SearchConditionAuthor,
|
||||
SearchConditionComplete,
|
||||
SearchConditionDeleted,
|
||||
SearchConditionGenre,
|
||||
SearchConditionLanguage,
|
||||
SearchConditionLibraryId,
|
||||
|
|
@ -414,6 +415,15 @@ export default Vue.extend({
|
|||
nValue: new SearchConditionOneShot(new SearchOperatorIsFalse()),
|
||||
}],
|
||||
},
|
||||
deleted: {
|
||||
values: [
|
||||
{
|
||||
name: this.$t('common.unavailable').toString(),
|
||||
value: new SearchConditionDeleted(new SearchOperatorIsTrue()),
|
||||
nValue: new SearchConditionDeleted(new SearchOperatorIsFalse()),
|
||||
},
|
||||
],
|
||||
},
|
||||
} as FiltersOptions
|
||||
},
|
||||
filterOptionsPanel(): FiltersOptions {
|
||||
|
|
@ -435,7 +445,7 @@ export default Vue.extend({
|
|||
},
|
||||
...this.filterOptions.genre,
|
||||
],
|
||||
anyAllSelector: true
|
||||
anyAllSelector: true,
|
||||
},
|
||||
tag: {
|
||||
name: this.$t('filter.tag').toString(),
|
||||
|
|
@ -610,7 +620,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) || route.query.complete || route.query.oneshot || route.query.sharingLabel) {
|
||||
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 || route.query.oneshot || route.query.sharingLabel || route.query.deleted) {
|
||||
activeFilters = {
|
||||
status: route.query.status || [],
|
||||
readStatus: route.query.readStatus || [],
|
||||
|
|
@ -623,6 +633,7 @@ export default Vue.extend({
|
|||
complete: route.query.complete || [],
|
||||
oneshot: route.query.oneshot || [],
|
||||
sharingLabel: route.query.sharingLabel || [],
|
||||
deleted: route.query.deleted || [],
|
||||
}
|
||||
authorRoles.forEach((role: string) => {
|
||||
activeFilters[role] = route.query[role] || []
|
||||
|
|
@ -661,6 +672,7 @@ export default Vue.extend({
|
|||
complete: this.$_.intersectionWith(filters.complete, extractFilterOptionsValues(this.filterOptionsList.complete.values), objIsEqual) || [],
|
||||
oneshot: this.$_.intersectionWith(filters.oneshot, extractFilterOptionsValues(this.filterOptionsList.oneshot.values), objIsEqual) || [],
|
||||
sharingLabel: this.$_.intersectionWith(filters.sharingLabel, extractFilterOptionsValues(this.filterOptions.sharingLabel), objIsEqual) || [],
|
||||
deleted: this.$_.intersectionWith(filters.deleted, extractFilterOptionsValues(this.filterOptionsList.deleted.values), objIsEqual) || [],
|
||||
} as any
|
||||
authorRoles.forEach((role: string) => {
|
||||
validFilter[role] = filters[role] || []
|
||||
|
|
@ -781,6 +793,7 @@ export default Vue.extend({
|
|||
if (this.filters.sharingLabel && this.filters.sharingLabel.length > 0) this.filtersMode?.sharingLabel?.allOf ? conditions.push(new SearchConditionAllOfSeries(this.filters.sharingLabel)) : conditions.push(new SearchConditionAnyOfSeries(this.filters.sharingLabel))
|
||||
if (this.filters.complete && this.filters.complete.length > 0) conditions.push(...this.filters.complete)
|
||||
if (this.filters.oneshot && this.filters.oneshot.length > 0) conditions.push(...this.filters.oneshot)
|
||||
if (this.filters.deleted && this.filters.deleted.length > 0) conditions.push(...this.filters.deleted)
|
||||
authorRoles.forEach((role: string) => {
|
||||
if (role in this.filters) {
|
||||
const authorConditions = this.filters[role].map((name: string) => {
|
||||
|
|
|
|||
|
|
@ -555,6 +555,7 @@ import {
|
|||
SearchConditionAnyOfBook,
|
||||
SearchConditionAuthor,
|
||||
SearchConditionBook,
|
||||
SearchConditionDeleted,
|
||||
SearchConditionGenre,
|
||||
SearchConditionLanguage,
|
||||
SearchConditionMediaProfile,
|
||||
|
|
@ -564,9 +565,11 @@ import {
|
|||
SearchConditionSeriesStatus,
|
||||
SearchConditionTag,
|
||||
SearchOperatorIs,
|
||||
SearchOperatorIsFalse,
|
||||
SearchOperatorIsNot,
|
||||
SearchOperatorIsNotNull,
|
||||
SearchOperatorIsNull,
|
||||
SearchOperatorIsTrue,
|
||||
} from '@/types/komga-search'
|
||||
import {objIsEqual} from '@/functions/object'
|
||||
import i18n from '@/i18n'
|
||||
|
|
@ -679,6 +682,15 @@ export default Vue.extend({
|
|||
},
|
||||
],
|
||||
},
|
||||
deleted: {
|
||||
values: [
|
||||
{
|
||||
name: this.$t('common.unavailable').toString(),
|
||||
value: new SearchConditionDeleted(new SearchOperatorIsTrue()),
|
||||
nValue: new SearchConditionDeleted(new SearchOperatorIsFalse()),
|
||||
},
|
||||
],
|
||||
},
|
||||
} as FiltersOptions
|
||||
},
|
||||
filterOptionsPanel(): FiltersOptions {
|
||||
|
|
@ -874,11 +886,12 @@ export default Vue.extend({
|
|||
|
||||
// get filter from query params and validate with available filter values
|
||||
let activeFilters = {} as FiltersActive
|
||||
if (route.query.readStatus || route.query.tag || route.query.mediaProfile || authorRoles.some(role => role in route.query)) {
|
||||
if (route.query.readStatus || route.query.tag || route.query.mediaProfile || authorRoles.some(role => role in route.query) || route.query.deleted) {
|
||||
activeFilters = {
|
||||
readStatus: route.query.readStatus || [],
|
||||
tag: route.query.tag || [],
|
||||
mediaProfile: route.query.mediaProfile || [],
|
||||
deleted: route.query.deleted || [],
|
||||
}
|
||||
authorRoles.forEach((role: string) => {
|
||||
activeFilters[role] = route.query[role] || []
|
||||
|
|
@ -898,6 +911,7 @@ export default Vue.extend({
|
|||
readStatus: this.$_.intersectionWith(filters.readStatus, extractFilterOptionsValues(this.filterOptionsList.readStatus.values), objIsEqual) || [],
|
||||
tag: this.$_.intersectionWith(filters.tag, extractFilterOptionsValues(this.filterOptions.tag), objIsEqual) || [],
|
||||
mediaProfile: this.$_.intersectionWith(filters.mediaProfile, extractFilterOptionsValues(this.filterOptionsPanel.mediaProfile.values), objIsEqual) || [],
|
||||
deleted: this.$_.intersectionWith(filters.deleted, extractFilterOptionsValues(this.filterOptionsList.deleted.values), objIsEqual) || [],
|
||||
} as any
|
||||
authorRoles.forEach((role: string) => {
|
||||
validFilter[role] = filters[role] || []
|
||||
|
|
@ -1039,6 +1053,7 @@ export default Vue.extend({
|
|||
if (this.filters.readStatus && this.filters.readStatus.length > 0) conditions.push(new SearchConditionAnyOfBook(this.filters.readStatus))
|
||||
if (this.filters.tag && this.filters.tag.length > 0) this.filtersMode?.tag?.allOf ? conditions.push(new SearchConditionAllOfBook(this.filters.tag)) : conditions.push(new SearchConditionAnyOfBook(this.filters.tag))
|
||||
if (this.filters.mediaProfile && this.filters.mediaProfile.length > 0) this.filtersMode?.mediaProfile?.allOf ? conditions.push(new SearchConditionAllOfBook(this.filters.mediaProfile)) : conditions.push(new SearchConditionAnyOfBook(this.filters.mediaProfile))
|
||||
if (this.filters.deleted && this.filters.deleted.length > 0) conditions.push(...this.filters.deleted)
|
||||
authorRoles.forEach((role: string) => {
|
||||
if (role in this.filters) {
|
||||
const authorConditions = this.filters[role].map((name: string) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue