mirror of
https://github.com/fallenbagel/jellyseerr.git
synced 2026-01-04 05:38:37 -05:00
feat(discover): support filtering by tmdb user vote count on discover page (#3407)
This commit is contained in:
@@ -4186,6 +4186,16 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
type: number
|
type: number
|
||||||
example: 10
|
example: 10
|
||||||
|
- in: query
|
||||||
|
name: voteCountGte
|
||||||
|
schema:
|
||||||
|
type: number
|
||||||
|
example: 7
|
||||||
|
- in: query
|
||||||
|
name: voteCountLte
|
||||||
|
schema:
|
||||||
|
type: number
|
||||||
|
example: 10
|
||||||
- in: query
|
- in: query
|
||||||
name: watchRegion
|
name: watchRegion
|
||||||
schema:
|
schema:
|
||||||
@@ -4465,6 +4475,16 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
type: number
|
type: number
|
||||||
example: 10
|
example: 10
|
||||||
|
- in: query
|
||||||
|
name: voteCountGte
|
||||||
|
schema:
|
||||||
|
type: number
|
||||||
|
example: 7
|
||||||
|
- in: query
|
||||||
|
name: voteCountLte
|
||||||
|
schema:
|
||||||
|
type: number
|
||||||
|
example: 10
|
||||||
- in: query
|
- in: query
|
||||||
name: watchRegion
|
name: watchRegion
|
||||||
schema:
|
schema:
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ interface DiscoverMovieOptions {
|
|||||||
withRuntimeLte?: string;
|
withRuntimeLte?: string;
|
||||||
voteAverageGte?: string;
|
voteAverageGte?: string;
|
||||||
voteAverageLte?: string;
|
voteAverageLte?: string;
|
||||||
|
voteCountGte?: string;
|
||||||
|
voteCountLte?: string;
|
||||||
originalLanguage?: string;
|
originalLanguage?: string;
|
||||||
genre?: string;
|
genre?: string;
|
||||||
studio?: string;
|
studio?: string;
|
||||||
@@ -83,6 +85,8 @@ interface DiscoverTvOptions {
|
|||||||
withRuntimeLte?: string;
|
withRuntimeLte?: string;
|
||||||
voteAverageGte?: string;
|
voteAverageGte?: string;
|
||||||
voteAverageLte?: string;
|
voteAverageLte?: string;
|
||||||
|
voteCountGte?: string;
|
||||||
|
voteCountLte?: string;
|
||||||
includeEmptyReleaseDate?: boolean;
|
includeEmptyReleaseDate?: boolean;
|
||||||
originalLanguage?: string;
|
originalLanguage?: string;
|
||||||
genre?: string;
|
genre?: string;
|
||||||
@@ -460,6 +464,8 @@ class TheMovieDb extends ExternalAPI {
|
|||||||
withRuntimeLte,
|
withRuntimeLte,
|
||||||
voteAverageGte,
|
voteAverageGte,
|
||||||
voteAverageLte,
|
voteAverageLte,
|
||||||
|
voteCountGte,
|
||||||
|
voteCountLte,
|
||||||
watchProviders,
|
watchProviders,
|
||||||
watchRegion,
|
watchRegion,
|
||||||
}: DiscoverMovieOptions = {}): Promise<TmdbSearchMovieResponse> => {
|
}: DiscoverMovieOptions = {}): Promise<TmdbSearchMovieResponse> => {
|
||||||
@@ -504,6 +510,8 @@ class TheMovieDb extends ExternalAPI {
|
|||||||
'with_runtime.lte': withRuntimeLte,
|
'with_runtime.lte': withRuntimeLte,
|
||||||
'vote_average.gte': voteAverageGte,
|
'vote_average.gte': voteAverageGte,
|
||||||
'vote_average.lte': voteAverageLte,
|
'vote_average.lte': voteAverageLte,
|
||||||
|
'vote_count.gte': voteCountGte,
|
||||||
|
'vote_count.lte': voteCountLte,
|
||||||
watch_region: watchRegion,
|
watch_region: watchRegion,
|
||||||
with_watch_providers: watchProviders,
|
with_watch_providers: watchProviders,
|
||||||
},
|
},
|
||||||
@@ -530,6 +538,8 @@ class TheMovieDb extends ExternalAPI {
|
|||||||
withRuntimeLte,
|
withRuntimeLte,
|
||||||
voteAverageGte,
|
voteAverageGte,
|
||||||
voteAverageLte,
|
voteAverageLte,
|
||||||
|
voteCountGte,
|
||||||
|
voteCountLte,
|
||||||
watchProviders,
|
watchProviders,
|
||||||
watchRegion,
|
watchRegion,
|
||||||
}: DiscoverTvOptions = {}): Promise<TmdbSearchTvResponse> => {
|
}: DiscoverTvOptions = {}): Promise<TmdbSearchTvResponse> => {
|
||||||
@@ -574,6 +584,8 @@ class TheMovieDb extends ExternalAPI {
|
|||||||
'with_runtime.lte': withRuntimeLte,
|
'with_runtime.lte': withRuntimeLte,
|
||||||
'vote_average.gte': voteAverageGte,
|
'vote_average.gte': voteAverageGte,
|
||||||
'vote_average.lte': voteAverageLte,
|
'vote_average.lte': voteAverageLte,
|
||||||
|
'vote_count.gte': voteCountGte,
|
||||||
|
'vote_count.lte': voteCountLte,
|
||||||
with_watch_providers: watchProviders,
|
with_watch_providers: watchProviders,
|
||||||
watch_region: watchRegion,
|
watch_region: watchRegion,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ const QueryFilterOptions = z.object({
|
|||||||
withRuntimeLte: z.coerce.string().optional(),
|
withRuntimeLte: z.coerce.string().optional(),
|
||||||
voteAverageGte: z.coerce.string().optional(),
|
voteAverageGte: z.coerce.string().optional(),
|
||||||
voteAverageLte: z.coerce.string().optional(),
|
voteAverageLte: z.coerce.string().optional(),
|
||||||
|
voteCountGte: z.coerce.string().optional(),
|
||||||
|
voteCountLte: z.coerce.string().optional(),
|
||||||
network: z.coerce.string().optional(),
|
network: z.coerce.string().optional(),
|
||||||
watchProviders: z.coerce.string().optional(),
|
watchProviders: z.coerce.string().optional(),
|
||||||
watchRegion: z.coerce.string().optional(),
|
watchRegion: z.coerce.string().optional(),
|
||||||
@@ -96,6 +98,8 @@ discoverRoutes.get('/movies', async (req, res, next) => {
|
|||||||
withRuntimeLte: query.withRuntimeLte,
|
withRuntimeLte: query.withRuntimeLte,
|
||||||
voteAverageGte: query.voteAverageGte,
|
voteAverageGte: query.voteAverageGte,
|
||||||
voteAverageLte: query.voteAverageLte,
|
voteAverageLte: query.voteAverageLte,
|
||||||
|
voteCountGte: query.voteCountGte,
|
||||||
|
voteCountLte: query.voteCountLte,
|
||||||
watchProviders: query.watchProviders,
|
watchProviders: query.watchProviders,
|
||||||
watchRegion: query.watchRegion,
|
watchRegion: query.watchRegion,
|
||||||
});
|
});
|
||||||
@@ -371,6 +375,8 @@ discoverRoutes.get('/tv', async (req, res, next) => {
|
|||||||
withRuntimeLte: query.withRuntimeLte,
|
withRuntimeLte: query.withRuntimeLte,
|
||||||
voteAverageGte: query.voteAverageGte,
|
voteAverageGte: query.voteAverageGte,
|
||||||
voteAverageLte: query.voteAverageLte,
|
voteAverageLte: query.voteAverageLte,
|
||||||
|
voteCountGte: query.voteCountGte,
|
||||||
|
voteCountLte: query.voteCountLte,
|
||||||
watchProviders: query.watchProviders,
|
watchProviders: query.watchProviders,
|
||||||
watchRegion: query.watchRegion,
|
watchRegion: query.watchRegion,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -35,8 +35,10 @@ const messages = defineMessages({
|
|||||||
ratingText: 'Ratings between {minValue} and {maxValue}',
|
ratingText: 'Ratings between {minValue} and {maxValue}',
|
||||||
clearfilters: 'Clear Active Filters',
|
clearfilters: 'Clear Active Filters',
|
||||||
tmdbuserscore: 'TMDB User Score',
|
tmdbuserscore: 'TMDB User Score',
|
||||||
|
tmdbuservotecount: 'TMDB User Vote Count',
|
||||||
runtime: 'Runtime',
|
runtime: 'Runtime',
|
||||||
streamingservices: 'Streaming Services',
|
streamingservices: 'Streaming Services',
|
||||||
|
voteCount: 'Number of votes between {minValue} and {maxValue}',
|
||||||
});
|
});
|
||||||
|
|
||||||
type FilterSlideoverProps = {
|
type FilterSlideoverProps = {
|
||||||
@@ -246,6 +248,45 @@ const FilterSlideover = ({
|
|||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<span className="text-lg font-semibold">
|
||||||
|
{intl.formatMessage(messages.tmdbuservotecount)}
|
||||||
|
</span>
|
||||||
|
<div className="relative z-0">
|
||||||
|
<MultiRangeSlider
|
||||||
|
min={0}
|
||||||
|
max={1000}
|
||||||
|
defaultMaxValue={
|
||||||
|
currentFilters.voteCountLte
|
||||||
|
? Number(currentFilters.voteCountLte)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
defaultMinValue={
|
||||||
|
currentFilters.voteCountGte
|
||||||
|
? Number(currentFilters.voteCountGte)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
onUpdateMin={(min) => {
|
||||||
|
updateQueryParams(
|
||||||
|
'voteCountGte',
|
||||||
|
min !== 0 && Number(currentFilters.voteCountLte) !== 1000
|
||||||
|
? min.toString()
|
||||||
|
: undefined
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
onUpdateMax={(max) => {
|
||||||
|
updateQueryParams(
|
||||||
|
'voteCountLte',
|
||||||
|
max !== 1000 && Number(currentFilters.voteCountGte) !== 0
|
||||||
|
? max.toString()
|
||||||
|
: undefined
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
subText={intl.formatMessage(messages.voteCount, {
|
||||||
|
minValue: currentFilters.voteCountGte ?? 0,
|
||||||
|
maxValue: currentFilters.voteCountLte ?? 1000,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<span className="text-lg font-semibold">
|
<span className="text-lg font-semibold">
|
||||||
{intl.formatMessage(messages.streamingservices)}
|
{intl.formatMessage(messages.streamingservices)}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -104,6 +104,8 @@ export const QueryFilterOptions = z.object({
|
|||||||
withRuntimeLte: z.string().optional(),
|
withRuntimeLte: z.string().optional(),
|
||||||
voteAverageGte: z.string().optional(),
|
voteAverageGte: z.string().optional(),
|
||||||
voteAverageLte: z.string().optional(),
|
voteAverageLte: z.string().optional(),
|
||||||
|
voteCountLte: z.string().optional(),
|
||||||
|
voteCountGte: z.string().optional(),
|
||||||
watchRegion: z.string().optional(),
|
watchRegion: z.string().optional(),
|
||||||
watchProviders: z.string().optional(),
|
watchProviders: z.string().optional(),
|
||||||
});
|
});
|
||||||
@@ -169,6 +171,14 @@ export const prepareFilterValues = (
|
|||||||
filterValues.voteAverageLte = values.voteAverageLte;
|
filterValues.voteAverageLte = values.voteAverageLte;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (values.voteCountGte) {
|
||||||
|
filterValues.voteCountGte = values.voteCountGte;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (values.voteCountLte) {
|
||||||
|
filterValues.voteCountLte = values.voteCountLte;
|
||||||
|
}
|
||||||
|
|
||||||
if (values.watchProviders) {
|
if (values.watchProviders) {
|
||||||
filterValues.watchProviders = values.watchProviders;
|
filterValues.watchProviders = values.watchProviders;
|
||||||
}
|
}
|
||||||
@@ -190,6 +200,12 @@ export const countActiveFilters = (filterValues: FilterOptions): number => {
|
|||||||
delete clonedFilters.voteAverageLte;
|
delete clonedFilters.voteAverageLte;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (clonedFilters.voteCountGte || filterValues.voteCountLte) {
|
||||||
|
totalCount += 1;
|
||||||
|
delete clonedFilters.voteCountGte;
|
||||||
|
delete clonedFilters.voteCountLte;
|
||||||
|
}
|
||||||
|
|
||||||
if (clonedFilters.withRuntimeGte || filterValues.withRuntimeLte) {
|
if (clonedFilters.withRuntimeGte || filterValues.withRuntimeLte) {
|
||||||
totalCount += 1;
|
totalCount += 1;
|
||||||
delete clonedFilters.withRuntimeGte;
|
delete clonedFilters.withRuntimeGte;
|
||||||
|
|||||||
@@ -76,7 +76,9 @@
|
|||||||
"components.Discover.FilterSlideover.streamingservices": "Streaming Services",
|
"components.Discover.FilterSlideover.streamingservices": "Streaming Services",
|
||||||
"components.Discover.FilterSlideover.studio": "Studio",
|
"components.Discover.FilterSlideover.studio": "Studio",
|
||||||
"components.Discover.FilterSlideover.tmdbuserscore": "TMDB User Score",
|
"components.Discover.FilterSlideover.tmdbuserscore": "TMDB User Score",
|
||||||
|
"components.Discover.FilterSlideover.tmdbuservotecount": "TMDB User Vote Count",
|
||||||
"components.Discover.FilterSlideover.to": "To",
|
"components.Discover.FilterSlideover.to": "To",
|
||||||
|
"components.Discover.FilterSlideover.voteCount": "Number of votes between {minValue} and {maxValue}",
|
||||||
"components.Discover.MovieGenreList.moviegenres": "Movie Genres",
|
"components.Discover.MovieGenreList.moviegenres": "Movie Genres",
|
||||||
"components.Discover.MovieGenreSlider.moviegenres": "Movie Genres",
|
"components.Discover.MovieGenreSlider.moviegenres": "Movie Genres",
|
||||||
"components.Discover.NetworkSlider.networks": "Networks",
|
"components.Discover.NetworkSlider.networks": "Networks",
|
||||||
|
|||||||
Reference in New Issue
Block a user