mirror of
https://github.com/rommapp/romm.git
synced 2026-02-18 23:42:07 +01:00
Enhance multi-value filter functionality with logic operators for genres, franchises, collections, companies, age ratings, regions, and languages. Update API and frontend components to support new filter states and logic. Refactor gallery filter store and API service to accommodate multi-value selections and maintain backward compatibility with single-value filters. Improve UI for filter options in the gallery app, including logic toggle buttons for better user interaction.
This commit is contained in:
@@ -349,6 +349,56 @@ def get_roms(
|
||||
str,
|
||||
Query(description="Order direction, either 'asc' or 'desc'."),
|
||||
] = "asc",
|
||||
# Logic operators for multi-value filters
|
||||
genres_logic: Annotated[
|
||||
str,
|
||||
Query(
|
||||
description="Logic operator for genres filter: 'any' (OR) or 'all' (AND).",
|
||||
alias="genres_logic",
|
||||
),
|
||||
] = "any",
|
||||
franchises_logic: Annotated[
|
||||
str,
|
||||
Query(
|
||||
description="Logic operator for franchises filter: 'any' (OR) or 'all' (AND).",
|
||||
alias="franchises_logic",
|
||||
),
|
||||
] = "any",
|
||||
collections_logic: Annotated[
|
||||
str,
|
||||
Query(
|
||||
description="Logic operator for collections filter: 'any' (OR) or 'all' (AND).",
|
||||
alias="collections_logic",
|
||||
),
|
||||
] = "any",
|
||||
companies_logic: Annotated[
|
||||
str,
|
||||
Query(
|
||||
description="Logic operator for companies filter: 'any' (OR) or 'all' (AND).",
|
||||
alias="companies_logic",
|
||||
),
|
||||
] = "any",
|
||||
age_ratings_logic: Annotated[
|
||||
str,
|
||||
Query(
|
||||
description="Logic operator for age ratings filter: 'any' (OR) or 'all' (AND).",
|
||||
alias="age_ratings_logic",
|
||||
),
|
||||
] = "any",
|
||||
regions_logic: Annotated[
|
||||
str,
|
||||
Query(
|
||||
description="Logic operator for regions filter: 'any' (OR) or 'all' (AND).",
|
||||
alias="regions_logic",
|
||||
),
|
||||
] = "any",
|
||||
languages_logic: Annotated[
|
||||
str,
|
||||
Query(
|
||||
description="Logic operator for languages filter: 'any' (OR) or 'all' (AND).",
|
||||
alias="languages_logic",
|
||||
),
|
||||
] = "any",
|
||||
) -> CustomLimitOffsetPage[SimpleRomSchema]:
|
||||
"""Retrieve roms."""
|
||||
|
||||
@@ -420,6 +470,14 @@ def get_roms(
|
||||
selected_status=selected_status,
|
||||
regions=regions,
|
||||
languages=languages,
|
||||
# Logic operators
|
||||
genres_logic=genres_logic,
|
||||
franchises_logic=franchises_logic,
|
||||
collections_logic=collections_logic,
|
||||
companies_logic=companies_logic,
|
||||
age_ratings_logic=age_ratings_logic,
|
||||
regions_logic=regions_logic,
|
||||
languages_logic=languages_logic,
|
||||
group_by_meta_id=group_by_meta_id,
|
||||
)
|
||||
|
||||
|
||||
@@ -436,6 +436,14 @@ class DBRomsHandler(DBBaseHandler):
|
||||
selected_status: str | None = None,
|
||||
regions: Sequence[str] | None = None,
|
||||
languages: Sequence[str] | None = None,
|
||||
# Logic operators for multi-value filters
|
||||
genres_logic: str = "any",
|
||||
franchises_logic: str = "any",
|
||||
collections_logic: str = "any",
|
||||
companies_logic: str = "any",
|
||||
age_ratings_logic: str = "any",
|
||||
regions_logic: str = "any",
|
||||
languages_logic: str = "any",
|
||||
user_id: int | None = None,
|
||||
session: Session = None,
|
||||
) -> Query[Rom]:
|
||||
@@ -597,25 +605,53 @@ class DBRomsHandler(DBBaseHandler):
|
||||
|
||||
# Apply metadata filters efficiently
|
||||
if genres:
|
||||
query = self.filter_by_genres(query, session=session, values=genres)
|
||||
query = self.filter_by_genres(
|
||||
query, session=session, values=genres, match_all=(genres_logic == "all")
|
||||
)
|
||||
if franchises:
|
||||
query = self.filter_by_franchises(query, session=session, values=franchises)
|
||||
query = self.filter_by_franchises(
|
||||
query,
|
||||
session=session,
|
||||
values=franchises,
|
||||
match_all=(franchises_logic == "all"),
|
||||
)
|
||||
if collections:
|
||||
query = self.filter_by_collections(
|
||||
query, session=session, values=collections
|
||||
query,
|
||||
session=session,
|
||||
values=collections,
|
||||
match_all=(collections_logic == "all"),
|
||||
)
|
||||
if companies:
|
||||
query = self.filter_by_companies(query, session=session, values=companies)
|
||||
query = self.filter_by_companies(
|
||||
query,
|
||||
session=session,
|
||||
values=companies,
|
||||
match_all=(companies_logic == "all"),
|
||||
)
|
||||
if age_ratings:
|
||||
query = self.filter_by_age_ratings(
|
||||
query, session=session, values=age_ratings
|
||||
query,
|
||||
session=session,
|
||||
values=age_ratings,
|
||||
match_all=(age_ratings_logic == "all"),
|
||||
)
|
||||
|
||||
# Apply rom-level filters
|
||||
if regions:
|
||||
query = self.filter_by_regions(query, session=session, values=regions)
|
||||
query = self.filter_by_regions(
|
||||
query,
|
||||
session=session,
|
||||
values=regions,
|
||||
match_all=(regions_logic == "all"),
|
||||
)
|
||||
if languages:
|
||||
query = self.filter_by_languages(query, session=session, values=languages)
|
||||
query = self.filter_by_languages(
|
||||
query,
|
||||
session=session,
|
||||
values=languages,
|
||||
match_all=(languages_logic == "all"),
|
||||
)
|
||||
|
||||
# The RomUser table is already joined if user_id is set
|
||||
if selected_status and user_id:
|
||||
|
||||
@@ -53,21 +53,37 @@ const {
|
||||
filterVerified,
|
||||
selectedGenre,
|
||||
filterGenres,
|
||||
selectedGenres,
|
||||
genresLogic,
|
||||
selectedFranchise,
|
||||
filterFranchises,
|
||||
selectedFranchises,
|
||||
franchisesLogic,
|
||||
selectedCollection,
|
||||
filterCollections,
|
||||
selectedCollections,
|
||||
collectionsLogic,
|
||||
selectedCompany,
|
||||
filterCompanies,
|
||||
selectedCompanies,
|
||||
companiesLogic,
|
||||
selectedAgeRating,
|
||||
filterAgeRatings,
|
||||
selectedAgeRatings,
|
||||
ageRatingsLogic,
|
||||
selectedStatus,
|
||||
filterStatuses,
|
||||
selectedStatuses,
|
||||
statusesLogic,
|
||||
selectedPlatform,
|
||||
selectedRegion,
|
||||
filterRegions,
|
||||
selectedRegions,
|
||||
regionsLogic,
|
||||
selectedLanguage,
|
||||
filterLanguages,
|
||||
selectedLanguages,
|
||||
languagesLogic,
|
||||
} = storeToRefs(galleryFilterStore);
|
||||
const { filteredRoms } = storeToRefs(romsStore);
|
||||
const { allPlatforms } = storeToRefs(platformsStore);
|
||||
@@ -94,13 +110,58 @@ const onFilterChange = debounce(
|
||||
? String(selectedPlatform.value.id)
|
||||
: null,
|
||||
genre: selectedGenre.value,
|
||||
genres:
|
||||
selectedGenres.value.length > 0 ? selectedGenres.value.join(",") : null,
|
||||
genresLogic: selectedGenres.value.length > 1 ? genresLogic.value : null,
|
||||
franchise: selectedFranchise.value,
|
||||
franchises:
|
||||
selectedFranchises.value.length > 0
|
||||
? selectedFranchises.value.join(",")
|
||||
: null,
|
||||
franchisesLogic:
|
||||
selectedFranchises.value.length > 1 ? franchisesLogic.value : null,
|
||||
collection: selectedCollection.value,
|
||||
collections:
|
||||
selectedCollections.value.length > 0
|
||||
? selectedCollections.value.join(",")
|
||||
: null,
|
||||
collectionsLogic:
|
||||
selectedCollections.value.length > 1 ? collectionsLogic.value : null,
|
||||
company: selectedCompany.value,
|
||||
companies:
|
||||
selectedCompanies.value.length > 0
|
||||
? selectedCompanies.value.join(",")
|
||||
: null,
|
||||
companiesLogic:
|
||||
selectedCompanies.value.length > 1 ? companiesLogic.value : null,
|
||||
ageRating: selectedAgeRating.value,
|
||||
ageRatings:
|
||||
selectedAgeRatings.value.length > 0
|
||||
? selectedAgeRatings.value.join(",")
|
||||
: null,
|
||||
ageRatingsLogic:
|
||||
selectedAgeRatings.value.length > 1 ? ageRatingsLogic.value : null,
|
||||
region: selectedRegion.value,
|
||||
regions:
|
||||
selectedRegions.value.length > 0
|
||||
? selectedRegions.value.join(",")
|
||||
: null,
|
||||
regionsLogic:
|
||||
selectedRegions.value.length > 1 ? regionsLogic.value : null,
|
||||
language: selectedLanguage.value,
|
||||
languages:
|
||||
selectedLanguages.value.length > 0
|
||||
? selectedLanguages.value.join(",")
|
||||
: null,
|
||||
languagesLogic:
|
||||
selectedLanguages.value.length > 1 ? languagesLogic.value : null,
|
||||
status: selectedStatus.value,
|
||||
statuses:
|
||||
selectedStatuses.value.length > 0
|
||||
? selectedStatuses.value.join(",")
|
||||
: null,
|
||||
statusesLogic:
|
||||
selectedStatuses.value.length > 1 ? statusesLogic.value : null,
|
||||
}).forEach(([key, value]) => {
|
||||
if (value) {
|
||||
url.searchParams.set(key, value);
|
||||
@@ -131,43 +192,67 @@ emitter?.on("filterRoms", onFilterChange);
|
||||
const filters = [
|
||||
{
|
||||
label: t("platform.genre"),
|
||||
selected: selectedGenre,
|
||||
selected: selectedGenres,
|
||||
items: filterGenres,
|
||||
logic: genresLogic,
|
||||
setLogic: (logic: "any" | "all") =>
|
||||
galleryFilterStore.setGenresLogic(logic),
|
||||
},
|
||||
{
|
||||
label: t("platform.franchise"),
|
||||
selected: selectedFranchise,
|
||||
selected: selectedFranchises,
|
||||
items: filterFranchises,
|
||||
logic: franchisesLogic,
|
||||
setLogic: (logic: "any" | "all") =>
|
||||
galleryFilterStore.setFranchisesLogic(logic),
|
||||
},
|
||||
{
|
||||
label: t("platform.collection"),
|
||||
selected: selectedCollection,
|
||||
selected: selectedCollections,
|
||||
items: filterCollections,
|
||||
logic: collectionsLogic,
|
||||
setLogic: (logic: "any" | "all") =>
|
||||
galleryFilterStore.setCollectionsLogic(logic),
|
||||
},
|
||||
{
|
||||
label: t("platform.company"),
|
||||
selected: selectedCompany,
|
||||
selected: selectedCompanies,
|
||||
items: filterCompanies,
|
||||
logic: companiesLogic,
|
||||
setLogic: (logic: "any" | "all") =>
|
||||
galleryFilterStore.setCompaniesLogic(logic),
|
||||
},
|
||||
{
|
||||
label: t("platform.age-rating"),
|
||||
selected: selectedAgeRating,
|
||||
selected: selectedAgeRatings,
|
||||
items: filterAgeRatings,
|
||||
logic: ageRatingsLogic,
|
||||
setLogic: (logic: "any" | "all") =>
|
||||
galleryFilterStore.setAgeRatingsLogic(logic),
|
||||
},
|
||||
{
|
||||
label: t("platform.region"),
|
||||
selected: selectedRegion,
|
||||
selected: selectedRegions,
|
||||
items: filterRegions,
|
||||
logic: regionsLogic,
|
||||
setLogic: (logic: "any" | "all") =>
|
||||
galleryFilterStore.setRegionsLogic(logic),
|
||||
},
|
||||
{
|
||||
label: t("platform.language"),
|
||||
selected: selectedLanguage,
|
||||
selected: selectedLanguages,
|
||||
items: filterLanguages,
|
||||
logic: languagesLogic,
|
||||
setLogic: (logic: "any" | "all") =>
|
||||
galleryFilterStore.setLanguagesLogic(logic),
|
||||
},
|
||||
{
|
||||
label: t("platform.status"),
|
||||
selected: selectedStatus,
|
||||
selected: selectedStatuses,
|
||||
items: filterStatuses,
|
||||
logic: statusesLogic,
|
||||
setLogic: (logic: "any" | "all") =>
|
||||
galleryFilterStore.setStatusesLogic(logic),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -185,38 +270,47 @@ let searchFilteredRoms = ref<SimpleRom[]>([]);
|
||||
|
||||
async function fetchSearchFilteredRoms() {
|
||||
try {
|
||||
const params = {
|
||||
searchTerm: searchTerm.value,
|
||||
platformId: romsStore.currentPlatform?.id ?? null,
|
||||
collectionId: romsStore.currentCollection?.id ?? null,
|
||||
virtualCollectionId: romsStore.currentVirtualCollection?.id ?? null,
|
||||
smartCollectionId: romsStore.currentSmartCollection?.id ?? null,
|
||||
limit: romsStore.fetchLimit,
|
||||
offset: romsStore.fetchOffset,
|
||||
orderBy: romsStore.orderBy,
|
||||
orderDir: romsStore.orderDir,
|
||||
// Exclude all other filters
|
||||
filterUnmatched: false,
|
||||
filterMatched: false,
|
||||
filterFavorites: null,
|
||||
filterDuplicates: null,
|
||||
filterPlayables: null,
|
||||
filterRA: null,
|
||||
filterMissing: null,
|
||||
filterVerified: null,
|
||||
// Single value filters - exclude
|
||||
selectedGenre: null,
|
||||
selectedFranchise: null,
|
||||
selectedCollection: null,
|
||||
selectedCompany: null,
|
||||
selectedAgeRating: null,
|
||||
selectedRegion: null,
|
||||
selectedLanguage: null,
|
||||
selectedStatus: null,
|
||||
// Multi-value filters - exclude
|
||||
selectedGenres: null,
|
||||
selectedFranchises: null,
|
||||
selectedCollections: null,
|
||||
selectedCompanies: null,
|
||||
selectedAgeRatings: null,
|
||||
selectedRegions: null,
|
||||
selectedLanguages: null,
|
||||
};
|
||||
|
||||
// Fetch ROMs with only search term applied (and current platform/collection context)
|
||||
const response = await cachedApiService.getRoms(
|
||||
{
|
||||
searchTerm: searchTerm.value,
|
||||
platformId: romsStore.currentPlatform?.id ?? null,
|
||||
collectionId: romsStore.currentCollection?.id ?? null,
|
||||
virtualCollectionId: romsStore.currentVirtualCollection?.id ?? null,
|
||||
smartCollectionId: romsStore.currentSmartCollection?.id ?? null,
|
||||
limit: romsStore.fetchLimit,
|
||||
offset: romsStore.fetchOffset,
|
||||
orderBy: romsStore.orderBy,
|
||||
orderDir: romsStore.orderDir,
|
||||
// Exclude all other filters
|
||||
filterUnmatched: false,
|
||||
filterMatched: false,
|
||||
filterFavorites: null,
|
||||
filterDuplicates: null,
|
||||
filterPlayables: null,
|
||||
filterRA: null,
|
||||
filterMissing: null,
|
||||
filterVerified: null,
|
||||
selectedGenre: null,
|
||||
selectedFranchise: null,
|
||||
selectedCollection: null,
|
||||
selectedCompany: null,
|
||||
selectedAgeRating: null,
|
||||
selectedRegion: null,
|
||||
selectedLanguage: null,
|
||||
selectedStatus: null,
|
||||
},
|
||||
() => {}, // No background update callback needed
|
||||
);
|
||||
const response = await cachedApiService.getRoms(params, () => {}); // No background update callback needed
|
||||
|
||||
searchFilteredRoms.value = response.data.items;
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch search-filtered ROMs:", error);
|
||||
@@ -280,6 +374,7 @@ onMounted(async () => {
|
||||
filterVerified: urlFilteredVerified,
|
||||
filterRA: urlFilteredRa,
|
||||
platform: urlPlatform,
|
||||
// Single value URL params (backward compatibility)
|
||||
genre: urlGenre,
|
||||
franchise: urlFranchise,
|
||||
collection: urlCollection,
|
||||
@@ -288,6 +383,23 @@ onMounted(async () => {
|
||||
region: urlRegion,
|
||||
language: urlLanguage,
|
||||
status: urlStatus,
|
||||
// Multi-value URL params
|
||||
genres: urlGenres,
|
||||
genresLogic: urlGenresLogic,
|
||||
franchises: urlFranchises,
|
||||
franchisesLogic: urlFranchisesLogic,
|
||||
collections: urlCollections,
|
||||
collectionsLogic: urlCollectionsLogic,
|
||||
companies: urlCompanies,
|
||||
companiesLogic: urlCompaniesLogic,
|
||||
ageRatings: urlAgeRatings,
|
||||
ageRatingsLogic: urlAgeRatingsLogic,
|
||||
regions: urlRegions,
|
||||
regionsLogic: urlRegionsLogic,
|
||||
languages: urlLanguages,
|
||||
languagesLogic: urlLanguagesLogic,
|
||||
statuses: urlStatuses,
|
||||
statusesLogic: urlStatusesLogic,
|
||||
} = router.currentRoute.value.query;
|
||||
|
||||
// Check for query params to set filters
|
||||
@@ -319,29 +431,102 @@ onMounted(async () => {
|
||||
const platform = platformsStore.get(Number(urlPlatform));
|
||||
if (platform) galleryFilterStore.setSelectedFilterPlatform(platform);
|
||||
}
|
||||
if (urlGenre !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterGenre(urlGenre as string);
|
||||
// Check for query params to set multi-value filters (prioritize over single values)
|
||||
if (urlGenres !== undefined) {
|
||||
const genres = (urlGenres as string).split(",").filter((g) => g.trim());
|
||||
galleryFilterStore.setSelectedFilterGenres(genres);
|
||||
if (urlGenresLogic !== undefined) {
|
||||
galleryFilterStore.setGenresLogic(urlGenresLogic as "any" | "all");
|
||||
}
|
||||
} else if (urlGenre !== undefined) {
|
||||
// Backward compatibility: if single genre is set, convert to multiselect
|
||||
galleryFilterStore.setSelectedFilterGenres([urlGenre as string]);
|
||||
}
|
||||
if (urlFranchise !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterFranchise(urlFranchise as string);
|
||||
|
||||
if (urlFranchises !== undefined) {
|
||||
const franchises = (urlFranchises as string)
|
||||
.split(",")
|
||||
.filter((f) => f.trim());
|
||||
galleryFilterStore.setSelectedFilterFranchises(franchises);
|
||||
if (urlFranchisesLogic !== undefined) {
|
||||
galleryFilterStore.setFranchisesLogic(
|
||||
urlFranchisesLogic as "any" | "all",
|
||||
);
|
||||
}
|
||||
} else if (urlFranchise !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterFranchises([urlFranchise as string]);
|
||||
}
|
||||
if (urlCollection !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterCollection(urlCollection as string);
|
||||
|
||||
if (urlCollections !== undefined) {
|
||||
const collections = (urlCollections as string)
|
||||
.split(",")
|
||||
.filter((c) => c.trim());
|
||||
galleryFilterStore.setSelectedFilterCollections(collections);
|
||||
if (urlCollectionsLogic !== undefined) {
|
||||
galleryFilterStore.setCollectionsLogic(
|
||||
urlCollectionsLogic as "any" | "all",
|
||||
);
|
||||
}
|
||||
} else if (urlCollection !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterCollections([urlCollection as string]);
|
||||
}
|
||||
if (urlCompany !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterCompany(urlCompany as string);
|
||||
|
||||
if (urlCompanies !== undefined) {
|
||||
const companies = (urlCompanies as string)
|
||||
.split(",")
|
||||
.filter((c) => c.trim());
|
||||
galleryFilterStore.setSelectedFilterCompanies(companies);
|
||||
if (urlCompaniesLogic !== undefined) {
|
||||
galleryFilterStore.setCompaniesLogic(urlCompaniesLogic as "any" | "all");
|
||||
}
|
||||
} else if (urlCompany !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterCompanies([urlCompany as string]);
|
||||
}
|
||||
if (urlAgeRating !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterAgeRating(urlAgeRating as string);
|
||||
|
||||
if (urlAgeRatings !== undefined) {
|
||||
const ageRatings = (urlAgeRatings as string)
|
||||
.split(",")
|
||||
.filter((a) => a.trim());
|
||||
galleryFilterStore.setSelectedFilterAgeRatings(ageRatings);
|
||||
if (urlAgeRatingsLogic !== undefined) {
|
||||
galleryFilterStore.setAgeRatingsLogic(
|
||||
urlAgeRatingsLogic as "any" | "all",
|
||||
);
|
||||
}
|
||||
} else if (urlAgeRating !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterAgeRatings([urlAgeRating as string]);
|
||||
}
|
||||
if (urlRegion !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterRegion(urlRegion as string);
|
||||
|
||||
if (urlRegions !== undefined) {
|
||||
const regions = (urlRegions as string).split(",").filter((r) => r.trim());
|
||||
galleryFilterStore.setSelectedFilterRegions(regions);
|
||||
if (urlRegionsLogic !== undefined) {
|
||||
galleryFilterStore.setRegionsLogic(urlRegionsLogic as "any" | "all");
|
||||
}
|
||||
} else if (urlRegion !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterRegions([urlRegion as string]);
|
||||
}
|
||||
if (urlLanguage !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterLanguage(urlLanguage as string);
|
||||
|
||||
if (urlLanguages !== undefined) {
|
||||
const languages = (urlLanguages as string)
|
||||
.split(",")
|
||||
.filter((l) => l.trim());
|
||||
galleryFilterStore.setSelectedFilterLanguages(languages);
|
||||
if (urlLanguagesLogic !== undefined) {
|
||||
galleryFilterStore.setLanguagesLogic(urlLanguagesLogic as "any" | "all");
|
||||
}
|
||||
} else if (urlLanguage !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterLanguages([urlLanguage as string]);
|
||||
}
|
||||
if (urlStatus !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterStatus(urlStatus as string);
|
||||
|
||||
if (urlStatuses !== undefined) {
|
||||
const statuses = (urlStatuses as string).split(",").filter((s) => s.trim());
|
||||
galleryFilterStore.setSelectedFilterStatuses(statuses);
|
||||
if (urlStatusesLogic !== undefined) {
|
||||
galleryFilterStore.setStatusesLogic(urlStatusesLogic as "any" | "all");
|
||||
}
|
||||
} else if (urlStatus !== undefined) {
|
||||
galleryFilterStore.setSelectedFilterStatuses([urlStatus as string]);
|
||||
}
|
||||
|
||||
// Check if search term is set in the URL (empty string is ok)
|
||||
@@ -429,12 +614,16 @@ onMounted(async () => {
|
||||
v-for="filter in filters"
|
||||
:key="filter.label"
|
||||
:tabindex="activeFilterDrawer ? 0 : -1"
|
||||
class="py-2"
|
||||
>
|
||||
<v-select
|
||||
v-model="filter.selected.value"
|
||||
:tabindex="activeFilterDrawer ? 0 : -1"
|
||||
hide-details
|
||||
clearable
|
||||
multiple
|
||||
chips
|
||||
closable-chips
|
||||
:label="filter.label"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
@@ -443,6 +632,24 @@ onMounted(async () => {
|
||||
nextTick(() => emitter?.emit('filterRoms', null))
|
||||
"
|
||||
/>
|
||||
<!-- AND/OR Logic Toggle -->
|
||||
<v-btn-toggle
|
||||
v-if="filter.selected.value.length > 1"
|
||||
:model-value="filter.logic.value"
|
||||
mandatory
|
||||
variant="outlined"
|
||||
density="compact"
|
||||
class="mt-2"
|
||||
@update:model-value="
|
||||
(value) => {
|
||||
filter.setLogic(value);
|
||||
nextTick(() => emitter?.emit('filterRoms', null));
|
||||
}
|
||||
"
|
||||
>
|
||||
<v-btn value="any" size="small">{{ t("common.filter.any") }}</v-btn>
|
||||
<v-btn value="all" size="small">{{ t("common.filter.all") }}</v-btn>
|
||||
</v-btn-toggle>
|
||||
</v-list-item>
|
||||
<v-list-item
|
||||
class="justify-center d-flex"
|
||||
|
||||
@@ -57,5 +57,9 @@
|
||||
"username-length": "Username must be between 3 and 255 characters",
|
||||
"virtual-collection": "Autogenerated collection",
|
||||
"virtual-collections": "Autogenerated collections",
|
||||
"warning": "WARNING:"
|
||||
"warning": "WARNING:",
|
||||
"filter": {
|
||||
"any": "Any",
|
||||
"all": "All"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ export interface GetRomsParams {
|
||||
filterMissing?: boolean | null;
|
||||
filterVerified?: boolean | null;
|
||||
groupByMetaId?: boolean;
|
||||
// Single value filters (for backward compatibility)
|
||||
selectedGenre?: string | null;
|
||||
selectedFranchise?: string | null;
|
||||
selectedCollection?: string | null;
|
||||
@@ -87,6 +88,23 @@ export interface GetRomsParams {
|
||||
selectedStatus?: string | null;
|
||||
selectedRegion?: string | null;
|
||||
selectedLanguage?: string | null;
|
||||
// Multi-value filters
|
||||
selectedGenres?: string[] | null;
|
||||
selectedFranchises?: string[] | null;
|
||||
selectedCollections?: string[] | null;
|
||||
selectedCompanies?: string[] | null;
|
||||
selectedAgeRatings?: string[] | null;
|
||||
selectedRegions?: string[] | null;
|
||||
selectedLanguages?: string[] | null;
|
||||
selectedStatuses?: string[] | null;
|
||||
// Logic operators for multi-value filters
|
||||
genresLogic?: string | null;
|
||||
franchisesLogic?: string | null;
|
||||
collectionsLogic?: string | null;
|
||||
companiesLogic?: string | null;
|
||||
ageRatingsLogic?: string | null;
|
||||
regionsLogic?: string | null;
|
||||
languagesLogic?: string | null;
|
||||
}
|
||||
|
||||
async function getRoms({
|
||||
@@ -116,36 +134,93 @@ async function getRoms({
|
||||
selectedStatus = null,
|
||||
selectedRegion = null,
|
||||
selectedLanguage = null,
|
||||
selectedGenres = null,
|
||||
selectedFranchises = null,
|
||||
selectedCollections = null,
|
||||
selectedCompanies = null,
|
||||
selectedAgeRatings = null,
|
||||
selectedRegions = null,
|
||||
selectedLanguages = null,
|
||||
selectedStatuses = null,
|
||||
// Logic operators
|
||||
genresLogic = null,
|
||||
franchisesLogic = null,
|
||||
collectionsLogic = null,
|
||||
companiesLogic = null,
|
||||
ageRatingsLogic = null,
|
||||
regionsLogic = null,
|
||||
languagesLogic = null,
|
||||
}: GetRomsParams): Promise<{ data: GetRomsResponse }> {
|
||||
// Helper function to handle single vs multi-value parameters
|
||||
const getFilterArray = (
|
||||
single: string | null,
|
||||
multi: string[] | null,
|
||||
): string[] | undefined => {
|
||||
if (multi && multi.length > 0) return multi;
|
||||
if (single) return [single];
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const params = {
|
||||
platform_id: platformId,
|
||||
collection_id: collectionId,
|
||||
virtual_collection_id: virtualCollectionId,
|
||||
smart_collection_id: smartCollectionId,
|
||||
search_term: searchTerm,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
order_by: orderBy,
|
||||
order_dir: orderDir,
|
||||
group_by_meta_id: groupByMetaId,
|
||||
genre: getFilterArray(selectedGenre, selectedGenres),
|
||||
franchise: getFilterArray(selectedFranchise, selectedFranchises),
|
||||
collection: getFilterArray(selectedCollection, selectedCollections),
|
||||
company: getFilterArray(selectedCompany, selectedCompanies),
|
||||
age_rating: getFilterArray(selectedAgeRating, selectedAgeRatings),
|
||||
selected_status: getStatusKeyForText(selectedStatus),
|
||||
region: getFilterArray(selectedRegion, selectedRegions),
|
||||
language: getFilterArray(selectedLanguage, selectedLanguages),
|
||||
// Logic operators
|
||||
genres_logic:
|
||||
selectedGenres && selectedGenres.length > 1
|
||||
? genresLogic || "any"
|
||||
: undefined,
|
||||
franchises_logic:
|
||||
selectedFranchises && selectedFranchises.length > 1
|
||||
? franchisesLogic || "any"
|
||||
: undefined,
|
||||
collections_logic:
|
||||
selectedCollections && selectedCollections.length > 1
|
||||
? collectionsLogic || "any"
|
||||
: undefined,
|
||||
companies_logic:
|
||||
selectedCompanies && selectedCompanies.length > 1
|
||||
? companiesLogic || "any"
|
||||
: undefined,
|
||||
age_ratings_logic:
|
||||
selectedAgeRatings && selectedAgeRatings.length > 1
|
||||
? ageRatingsLogic || "any"
|
||||
: undefined,
|
||||
regions_logic:
|
||||
selectedRegions && selectedRegions.length > 1
|
||||
? regionsLogic || "any"
|
||||
: undefined,
|
||||
languages_logic:
|
||||
selectedLanguages && selectedLanguages.length > 1
|
||||
? languagesLogic || "any"
|
||||
: undefined,
|
||||
...(filterUnmatched ? { matched: false } : {}),
|
||||
...(filterMatched ? { matched: true } : {}),
|
||||
...(filterFavorites !== null ? { favorite: filterFavorites } : {}),
|
||||
...(filterDuplicates !== null ? { duplicate: filterDuplicates } : {}),
|
||||
...(filterPlayables !== null ? { playable: filterPlayables } : {}),
|
||||
...(filterMissing !== null ? { missing: filterMissing } : {}),
|
||||
...(filterRA !== null ? { has_ra: filterRA } : {}),
|
||||
...(filterVerified !== null ? { verified: filterVerified } : {}),
|
||||
};
|
||||
|
||||
return api.get(`/roms`, {
|
||||
params: {
|
||||
platform_id: platformId,
|
||||
collection_id: collectionId,
|
||||
virtual_collection_id: virtualCollectionId,
|
||||
smart_collection_id: smartCollectionId,
|
||||
search_term: searchTerm,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
order_by: orderBy,
|
||||
order_dir: orderDir,
|
||||
group_by_meta_id: groupByMetaId,
|
||||
genre: selectedGenre ? [selectedGenre] : undefined,
|
||||
franchise: selectedFranchise ? [selectedFranchise] : undefined,
|
||||
collection: selectedCollection ? [selectedCollection] : undefined,
|
||||
company: selectedCompany ? [selectedCompany] : undefined,
|
||||
age_rating: selectedAgeRating ? [selectedAgeRating] : undefined,
|
||||
selected_status: getStatusKeyForText(selectedStatus),
|
||||
region: selectedRegion ? [selectedRegion] : undefined,
|
||||
language: selectedLanguage ? [selectedLanguage] : undefined,
|
||||
...(filterUnmatched ? { matched: false } : {}),
|
||||
...(filterMatched ? { matched: true } : {}),
|
||||
...(filterFavorites !== null ? { favorite: filterFavorites } : {}),
|
||||
...(filterDuplicates !== null ? { duplicate: filterDuplicates } : {}),
|
||||
...(filterPlayables !== null ? { playable: filterPlayables } : {}),
|
||||
...(filterMissing !== null ? { missing: filterMissing } : {}),
|
||||
...(filterRA !== null ? { has_ra: filterRA } : {}),
|
||||
...(filterVerified !== null ? { verified: filterVerified } : {}),
|
||||
},
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
83
frontend/src/services/cache/api.ts
vendored
83
frontend/src/services/cache/api.ts
vendored
@@ -11,6 +11,22 @@ import cacheService from "@/services/cache";
|
||||
import { getStatusKeyForText } from "@/utils";
|
||||
|
||||
class CachedApiService {
|
||||
// Helper function to handle single vs multi-value parameters
|
||||
private getFilterArray(
|
||||
single: string | null | undefined,
|
||||
multi: string[] | null | undefined,
|
||||
): string[] | undefined {
|
||||
const result = (() => {
|
||||
if (multi && multi.length > 0) return multi;
|
||||
if (single) return [single];
|
||||
return undefined;
|
||||
})();
|
||||
// Only log non-empty results to reduce console noise
|
||||
if (result) {
|
||||
console.log("CachedApiService getFilterArray - result:", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private createRequestConfig(
|
||||
method: Method,
|
||||
url: string,
|
||||
@@ -40,20 +56,61 @@ class CachedApiService {
|
||||
order_by: params.orderBy,
|
||||
order_dir: params.orderDir,
|
||||
group_by_meta_id: params.groupByMetaId,
|
||||
genre: params.selectedGenre ? [params.selectedGenre] : undefined,
|
||||
franchise: params.selectedFranchise
|
||||
? [params.selectedFranchise]
|
||||
: undefined,
|
||||
collection: params.selectedCollection
|
||||
? [params.selectedCollection]
|
||||
: undefined,
|
||||
company: params.selectedCompany ? [params.selectedCompany] : undefined,
|
||||
age_rating: params.selectedAgeRating
|
||||
? [params.selectedAgeRating]
|
||||
: undefined,
|
||||
genre: this.getFilterArray(params.selectedGenre, params.selectedGenres),
|
||||
franchise: this.getFilterArray(
|
||||
params.selectedFranchise,
|
||||
params.selectedFranchises,
|
||||
),
|
||||
collection: this.getFilterArray(
|
||||
params.selectedCollection,
|
||||
params.selectedCollections,
|
||||
),
|
||||
company: this.getFilterArray(
|
||||
params.selectedCompany,
|
||||
params.selectedCompanies,
|
||||
),
|
||||
age_rating: this.getFilterArray(
|
||||
params.selectedAgeRating,
|
||||
params.selectedAgeRatings,
|
||||
),
|
||||
selected_status: getStatusKeyForText(params.selectedStatus ?? null),
|
||||
region: params.selectedRegion ? [params.selectedRegion] : undefined,
|
||||
language: params.selectedLanguage ? [params.selectedLanguage] : undefined,
|
||||
region: this.getFilterArray(
|
||||
params.selectedRegion,
|
||||
params.selectedRegions,
|
||||
),
|
||||
language: this.getFilterArray(
|
||||
params.selectedLanguage,
|
||||
params.selectedLanguages,
|
||||
),
|
||||
// Logic operators
|
||||
genres_logic:
|
||||
params.selectedGenres && params.selectedGenres.length > 1
|
||||
? params.genresLogic || "any"
|
||||
: undefined,
|
||||
franchises_logic:
|
||||
params.selectedFranchises && params.selectedFranchises.length > 1
|
||||
? params.franchisesLogic || "any"
|
||||
: undefined,
|
||||
collections_logic:
|
||||
params.selectedCollections && params.selectedCollections.length > 1
|
||||
? params.collectionsLogic || "any"
|
||||
: undefined,
|
||||
companies_logic:
|
||||
params.selectedCompanies && params.selectedCompanies.length > 1
|
||||
? params.companiesLogic || "any"
|
||||
: undefined,
|
||||
age_ratings_logic:
|
||||
params.selectedAgeRatings && params.selectedAgeRatings.length > 1
|
||||
? params.ageRatingsLogic || "any"
|
||||
: undefined,
|
||||
regions_logic:
|
||||
params.selectedRegions && params.selectedRegions.length > 1
|
||||
? params.regionsLogic || "any"
|
||||
: undefined,
|
||||
languages_logic:
|
||||
params.selectedLanguages && params.selectedLanguages.length > 1
|
||||
? params.languagesLogic || "any"
|
||||
: undefined,
|
||||
...(params.filterUnmatched ? { matched: false } : {}),
|
||||
...(params.filterMatched ? { matched: true } : {}),
|
||||
...(params.filterFavorites !== null
|
||||
|
||||
@@ -35,14 +35,33 @@ const defaultFilterState = {
|
||||
filterMissing: null as boolean | null, // null = all, true = missing, false = not missing
|
||||
filterVerified: null as boolean | null, // null = all, true = verified, false = not verified
|
||||
selectedPlatform: null as Platform | null,
|
||||
selectedPlatforms: [] as Platform[],
|
||||
selectedGenre: null as string | null,
|
||||
selectedGenres: [] as string[],
|
||||
selectedFranchise: null as string | null,
|
||||
selectedFranchises: [] as string[],
|
||||
selectedCollection: null as string | null,
|
||||
selectedCollections: [] as string[],
|
||||
selectedCompany: null as string | null,
|
||||
selectedCompanies: [] as string[],
|
||||
selectedAgeRating: null as string | null,
|
||||
selectedAgeRatings: [] as string[],
|
||||
selectedRegion: null as string | null,
|
||||
selectedRegions: [] as string[],
|
||||
selectedLanguage: null as string | null,
|
||||
selectedLanguages: [] as string[],
|
||||
selectedStatus: null as string | null,
|
||||
selectedStatuses: [] as string[],
|
||||
// Logic operators for multi-select filters
|
||||
platformsLogic: "any" as "any" | "all",
|
||||
genresLogic: "any" as "any" | "all",
|
||||
franchisesLogic: "any" as "any" | "all",
|
||||
collectionsLogic: "any" as "any" | "all",
|
||||
companiesLogic: "any" as "any" | "all",
|
||||
ageRatingsLogic: "any" as "any" | "all",
|
||||
regionsLogic: "any" as "any" | "all",
|
||||
languagesLogic: "any" as "any" | "all",
|
||||
statusesLogic: "any" as "any" | "all",
|
||||
};
|
||||
|
||||
export default defineStore("galleryFilter", {
|
||||
@@ -81,30 +100,84 @@ export default defineStore("galleryFilter", {
|
||||
? this.filterPlatforms.find((p) => p.id === platform.id) || null
|
||||
: null;
|
||||
},
|
||||
setSelectedFilterPlatforms(platforms: Platform[]) {
|
||||
this.selectedPlatforms = platforms;
|
||||
},
|
||||
setPlatformsLogic(logic: "any" | "all") {
|
||||
this.platformsLogic = logic;
|
||||
},
|
||||
setSelectedFilterGenre(genre: string) {
|
||||
this.selectedGenre = genre;
|
||||
},
|
||||
setSelectedFilterGenres(genres: string[]) {
|
||||
this.selectedGenres = genres;
|
||||
},
|
||||
setGenresLogic(logic: "any" | "all") {
|
||||
this.genresLogic = logic;
|
||||
},
|
||||
setSelectedFilterFranchise(franchise: string) {
|
||||
this.selectedFranchise = franchise;
|
||||
},
|
||||
setSelectedFilterFranchises(franchises: string[]) {
|
||||
this.selectedFranchises = franchises;
|
||||
},
|
||||
setFranchisesLogic(logic: "any" | "all") {
|
||||
this.franchisesLogic = logic;
|
||||
},
|
||||
setSelectedFilterCollection(collection: string) {
|
||||
this.selectedCollection = collection;
|
||||
},
|
||||
setSelectedFilterCollections(collections: string[]) {
|
||||
this.selectedCollections = collections;
|
||||
},
|
||||
setCollectionsLogic(logic: "any" | "all") {
|
||||
this.collectionsLogic = logic;
|
||||
},
|
||||
setSelectedFilterCompany(company: string) {
|
||||
this.selectedCompany = company;
|
||||
},
|
||||
setSelectedFilterCompanies(companies: string[]) {
|
||||
this.selectedCompanies = companies;
|
||||
},
|
||||
setCompaniesLogic(logic: "any" | "all") {
|
||||
this.companiesLogic = logic;
|
||||
},
|
||||
setSelectedFilterAgeRating(ageRating: string) {
|
||||
this.selectedAgeRating = ageRating;
|
||||
},
|
||||
setSelectedFilterAgeRatings(ageRatings: string[]) {
|
||||
this.selectedAgeRatings = ageRatings;
|
||||
},
|
||||
setAgeRatingsLogic(logic: "any" | "all") {
|
||||
this.ageRatingsLogic = logic;
|
||||
},
|
||||
setSelectedFilterRegion(region: string) {
|
||||
this.selectedRegion = region;
|
||||
},
|
||||
setSelectedFilterRegions(regions: string[]) {
|
||||
this.selectedRegions = regions;
|
||||
},
|
||||
setRegionsLogic(logic: "any" | "all") {
|
||||
this.regionsLogic = logic;
|
||||
},
|
||||
setSelectedFilterLanguage(language: string) {
|
||||
this.selectedLanguage = language;
|
||||
},
|
||||
setSelectedFilterLanguages(languages: string[]) {
|
||||
this.selectedLanguages = languages;
|
||||
},
|
||||
setLanguagesLogic(logic: "any" | "all") {
|
||||
this.languagesLogic = logic;
|
||||
},
|
||||
setSelectedFilterStatus(status: string) {
|
||||
this.selectedStatus = status;
|
||||
},
|
||||
setSelectedFilterStatuses(statuses: string[]) {
|
||||
this.selectedStatuses = statuses;
|
||||
},
|
||||
setStatusesLogic(logic: "any" | "all") {
|
||||
this.statusesLogic = logic;
|
||||
},
|
||||
setFilterUnmatched(value: boolean) {
|
||||
this.filterUnmatched = value;
|
||||
this.filterMatched = false;
|
||||
@@ -282,14 +355,23 @@ export default defineStore("galleryFilter", {
|
||||
this.filterMissing !== null ||
|
||||
this.filterVerified !== null ||
|
||||
this.selectedPlatform ||
|
||||
this.selectedPlatforms.length > 0 ||
|
||||
this.selectedGenre ||
|
||||
this.selectedGenres.length > 0 ||
|
||||
this.selectedFranchise ||
|
||||
this.selectedFranchises.length > 0 ||
|
||||
this.selectedCollection ||
|
||||
this.selectedCollections.length > 0 ||
|
||||
this.selectedCompany ||
|
||||
this.selectedCompanies.length > 0 ||
|
||||
this.selectedAgeRating ||
|
||||
this.selectedAgeRatings.length > 0 ||
|
||||
this.selectedRegion ||
|
||||
this.selectedRegions.length > 0 ||
|
||||
this.selectedLanguage ||
|
||||
this.selectedStatus,
|
||||
this.selectedLanguages.length > 0 ||
|
||||
this.selectedStatus ||
|
||||
this.selectedStatuses.length > 0,
|
||||
);
|
||||
},
|
||||
reset() {
|
||||
@@ -297,14 +379,23 @@ export default defineStore("galleryFilter", {
|
||||
},
|
||||
resetFilters() {
|
||||
this.selectedPlatform = null;
|
||||
this.selectedPlatforms = [];
|
||||
this.selectedGenre = null;
|
||||
this.selectedGenres = [];
|
||||
this.selectedFranchise = null;
|
||||
this.selectedFranchises = [];
|
||||
this.selectedCollection = null;
|
||||
this.selectedCollections = [];
|
||||
this.selectedCompany = null;
|
||||
this.selectedCompanies = [];
|
||||
this.selectedAgeRating = null;
|
||||
this.selectedAgeRatings = [];
|
||||
this.selectedRegion = null;
|
||||
this.selectedRegions = [];
|
||||
this.selectedLanguage = null;
|
||||
this.selectedLanguages = [];
|
||||
this.selectedStatus = null;
|
||||
this.selectedStatuses = [];
|
||||
this.filterUnmatched = false;
|
||||
this.filterMatched = false;
|
||||
this.filterFavorites = null;
|
||||
@@ -313,6 +404,16 @@ export default defineStore("galleryFilter", {
|
||||
this.filterRA = null;
|
||||
this.filterMissing = null;
|
||||
this.filterVerified = null;
|
||||
// Reset logic operators to default
|
||||
this.platformsLogic = "any";
|
||||
this.genresLogic = "any";
|
||||
this.franchisesLogic = "any";
|
||||
this.collectionsLogic = "any";
|
||||
this.companiesLogic = "any";
|
||||
this.ageRatingsLogic = "any";
|
||||
this.regionsLogic = "any";
|
||||
this.languagesLogic = "any";
|
||||
this.statusesLogic = "any";
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -96,8 +96,8 @@ export default defineStore("roms", {
|
||||
},
|
||||
// Fetching multiple roms
|
||||
_buildRequestParams(galleryFilter: GalleryFilterStore) {
|
||||
return {
|
||||
...galleryFilter.$state,
|
||||
const params = {
|
||||
searchTerm: galleryFilter.searchTerm,
|
||||
platformId:
|
||||
this.currentPlatform?.id ??
|
||||
galleryFilter.selectedPlatform?.id ??
|
||||
@@ -110,7 +110,90 @@ export default defineStore("roms", {
|
||||
orderBy: this.orderBy,
|
||||
orderDir: this.orderDir,
|
||||
groupByMetaId: this._shouldGroupRoms() && this.onGalleryView,
|
||||
filterUnmatched: galleryFilter.filterUnmatched,
|
||||
filterMatched: galleryFilter.filterMatched,
|
||||
filterFavorites: galleryFilter.filterFavorites,
|
||||
filterDuplicates: galleryFilter.filterDuplicates,
|
||||
filterPlayables: galleryFilter.filterPlayables,
|
||||
filterRA: galleryFilter.filterRA,
|
||||
filterMissing: galleryFilter.filterMissing,
|
||||
filterVerified: galleryFilter.filterVerified,
|
||||
// Single value filters (backward compatibility - only use if multiselect is empty)
|
||||
selectedGenre:
|
||||
galleryFilter.selectedGenres.length > 0
|
||||
? null
|
||||
: galleryFilter.selectedGenre,
|
||||
selectedFranchise:
|
||||
galleryFilter.selectedFranchises.length > 0
|
||||
? null
|
||||
: galleryFilter.selectedFranchise,
|
||||
selectedCollection:
|
||||
galleryFilter.selectedCollections.length > 0
|
||||
? null
|
||||
: galleryFilter.selectedCollection,
|
||||
selectedCompany:
|
||||
galleryFilter.selectedCompanies.length > 0
|
||||
? null
|
||||
: galleryFilter.selectedCompany,
|
||||
selectedAgeRating:
|
||||
galleryFilter.selectedAgeRatings.length > 0
|
||||
? null
|
||||
: galleryFilter.selectedAgeRating,
|
||||
selectedStatus:
|
||||
galleryFilter.selectedStatuses.length > 0
|
||||
? null
|
||||
: galleryFilter.selectedStatus,
|
||||
selectedRegion:
|
||||
galleryFilter.selectedRegions.length > 0
|
||||
? null
|
||||
: galleryFilter.selectedRegion,
|
||||
selectedLanguage:
|
||||
galleryFilter.selectedLanguages.length > 0
|
||||
? null
|
||||
: galleryFilter.selectedLanguage,
|
||||
// Multi-value filters
|
||||
selectedGenres:
|
||||
galleryFilter.selectedGenres.length > 0
|
||||
? galleryFilter.selectedGenres
|
||||
: null,
|
||||
selectedFranchises:
|
||||
galleryFilter.selectedFranchises.length > 0
|
||||
? galleryFilter.selectedFranchises
|
||||
: null,
|
||||
selectedCollections:
|
||||
galleryFilter.selectedCollections.length > 0
|
||||
? galleryFilter.selectedCollections
|
||||
: null,
|
||||
selectedCompanies:
|
||||
galleryFilter.selectedCompanies.length > 0
|
||||
? galleryFilter.selectedCompanies
|
||||
: null,
|
||||
selectedAgeRatings:
|
||||
galleryFilter.selectedAgeRatings.length > 0
|
||||
? galleryFilter.selectedAgeRatings
|
||||
: null,
|
||||
selectedRegions:
|
||||
galleryFilter.selectedRegions.length > 0
|
||||
? galleryFilter.selectedRegions
|
||||
: null,
|
||||
selectedLanguages:
|
||||
galleryFilter.selectedLanguages.length > 0
|
||||
? galleryFilter.selectedLanguages
|
||||
: null,
|
||||
selectedStatuses:
|
||||
galleryFilter.selectedStatuses.length > 0
|
||||
? galleryFilter.selectedStatuses
|
||||
: null,
|
||||
// Logic operators
|
||||
genresLogic: galleryFilter.genresLogic,
|
||||
franchisesLogic: galleryFilter.franchisesLogic,
|
||||
collectionsLogic: galleryFilter.collectionsLogic,
|
||||
companiesLogic: galleryFilter.companiesLogic,
|
||||
ageRatingsLogic: galleryFilter.ageRatingsLogic,
|
||||
regionsLogic: galleryFilter.regionsLogic,
|
||||
languagesLogic: galleryFilter.languagesLogic,
|
||||
};
|
||||
return params;
|
||||
},
|
||||
_postFetchRoms(response: GetRomsResponse, concat: boolean) {
|
||||
const { items, offset, total, char_index, rom_id_index } = response;
|
||||
|
||||
Reference in New Issue
Block a user