mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
feat(ui): added content ratings for tv shows and movie ratings (#878)
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -38,6 +38,8 @@ config/settings.json
|
|||||||
# logs
|
# logs
|
||||||
config/logs/*.log*
|
config/logs/*.log*
|
||||||
config/logs/*.json
|
config/logs/*.json
|
||||||
|
config/logs/*.log.gz
|
||||||
|
config/logs/*-audit.json
|
||||||
|
|
||||||
# anidb mapping file
|
# anidb mapping file
|
||||||
config/anime-list.xml
|
config/anime-list.xml
|
||||||
|
@@ -644,6 +644,41 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
releaseDate:
|
releaseDate:
|
||||||
type: string
|
type: string
|
||||||
|
releases:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
results:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
iso_3166_1:
|
||||||
|
type: string
|
||||||
|
example: 'US'
|
||||||
|
rating:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
release_dates:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
certification:
|
||||||
|
type: string
|
||||||
|
example: 'PG-13'
|
||||||
|
iso_639_1:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
note:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
example: 'Blu ray'
|
||||||
|
release_date:
|
||||||
|
type: string
|
||||||
|
example: '2017-07-12T00:00:00.000Z'
|
||||||
|
type:
|
||||||
|
type: number
|
||||||
|
example: 1
|
||||||
revenue:
|
revenue:
|
||||||
type: number
|
type: number
|
||||||
nullable: true
|
nullable: true
|
||||||
@@ -752,6 +787,20 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
posterPath:
|
posterPath:
|
||||||
type: string
|
type: string
|
||||||
|
contentRatings:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
results:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
iso_3166_1:
|
||||||
|
type: string
|
||||||
|
example: 'US'
|
||||||
|
rating:
|
||||||
|
type: string
|
||||||
|
example: 'TV-14'
|
||||||
createdBy:
|
createdBy:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
|
@@ -145,7 +145,7 @@ class TheMovieDb extends ExternalAPI {
|
|||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
language,
|
language,
|
||||||
append_to_response: 'credits,external_ids,videos',
|
append_to_response: 'credits,external_ids,videos,release_dates',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
43200
|
43200
|
||||||
@@ -171,7 +171,7 @@ class TheMovieDb extends ExternalAPI {
|
|||||||
params: {
|
params: {
|
||||||
language,
|
language,
|
||||||
append_to_response:
|
append_to_response:
|
||||||
'aggregate_credits,credits,external_ids,keywords,videos',
|
'aggregate_credits,credits,external_ids,keywords,videos,content_ratings',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
43200
|
43200
|
||||||
|
@@ -136,6 +136,7 @@ export interface TmdbMovieDetails {
|
|||||||
name: string;
|
name: string;
|
||||||
}[];
|
}[];
|
||||||
release_date: string;
|
release_date: string;
|
||||||
|
release_dates: TmdbMovieReleaseResult;
|
||||||
revenue: number;
|
revenue: number;
|
||||||
runtime?: number;
|
runtime?: number;
|
||||||
spoken_languages: {
|
spoken_languages: {
|
||||||
@@ -205,6 +206,7 @@ export interface TmdbTvSeasonResult {
|
|||||||
export interface TmdbTvDetails {
|
export interface TmdbTvDetails {
|
||||||
id: number;
|
id: number;
|
||||||
backdrop_path?: string;
|
backdrop_path?: string;
|
||||||
|
content_ratings: TmdbTvRatingResult;
|
||||||
created_by: {
|
created_by: {
|
||||||
id: number;
|
id: number;
|
||||||
credit_id: string;
|
credit_id: string;
|
||||||
@@ -272,6 +274,29 @@ export interface TmdbVideoResult {
|
|||||||
results: TmdbVideo[];
|
results: TmdbVideo[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TmdbTvRatingResult {
|
||||||
|
results: TmdbRating[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TmdbRating {
|
||||||
|
iso_3166_1: string;
|
||||||
|
rating: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TmdbMovieReleaseResult {
|
||||||
|
results: TmdbRelease[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TmdbRelease extends TmdbRating {
|
||||||
|
release_dates: {
|
||||||
|
certification: string;
|
||||||
|
iso_639_1?: string;
|
||||||
|
note?: string;
|
||||||
|
release_date: string;
|
||||||
|
type: number;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface TmdbKeyword {
|
export interface TmdbKeyword {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -316,6 +341,7 @@ export interface TmdbPersonCredit {
|
|||||||
adult: boolean;
|
adult: boolean;
|
||||||
release_date: string;
|
release_date: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TmdbPersonCreditCast extends TmdbPersonCredit {
|
export interface TmdbPersonCreditCast extends TmdbPersonCredit {
|
||||||
character: string;
|
character: string;
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,7 @@
|
|||||||
import type { TmdbMovieDetails } from '../api/themoviedb/interfaces';
|
import type {
|
||||||
|
TmdbMovieDetails,
|
||||||
|
TmdbMovieReleaseResult,
|
||||||
|
} from '../api/themoviedb/interfaces';
|
||||||
import {
|
import {
|
||||||
ProductionCompany,
|
ProductionCompany,
|
||||||
Genre,
|
Genre,
|
||||||
@@ -48,6 +51,7 @@ export interface MovieDetails {
|
|||||||
name: string;
|
name: string;
|
||||||
}[];
|
}[];
|
||||||
releaseDate: string;
|
releaseDate: string;
|
||||||
|
releases: TmdbMovieReleaseResult;
|
||||||
revenue: number;
|
revenue: number;
|
||||||
runtime?: number;
|
runtime?: number;
|
||||||
spokenLanguages: {
|
spokenLanguages: {
|
||||||
@@ -95,6 +99,7 @@ export const mapMovieDetails = (
|
|||||||
})),
|
})),
|
||||||
productionCountries: movie.production_countries,
|
productionCountries: movie.production_countries,
|
||||||
releaseDate: movie.release_date,
|
releaseDate: movie.release_date,
|
||||||
|
releases: movie.release_dates,
|
||||||
revenue: movie.revenue,
|
revenue: movie.revenue,
|
||||||
spokenLanguages: movie.spoken_languages,
|
spokenLanguages: movie.spoken_languages,
|
||||||
status: movie.status,
|
status: movie.status,
|
||||||
|
@@ -15,6 +15,7 @@ import type {
|
|||||||
TmdbTvSeasonResult,
|
TmdbTvSeasonResult,
|
||||||
TmdbTvDetails,
|
TmdbTvDetails,
|
||||||
TmdbSeasonWithEpisodes,
|
TmdbSeasonWithEpisodes,
|
||||||
|
TmdbTvRatingResult,
|
||||||
} from '../api/themoviedb/interfaces';
|
} from '../api/themoviedb/interfaces';
|
||||||
import type Media from '../entity/Media';
|
import type Media from '../entity/Media';
|
||||||
import { Video } from './Movie';
|
import { Video } from './Movie';
|
||||||
@@ -58,6 +59,7 @@ export interface TvDetails {
|
|||||||
id: number;
|
id: number;
|
||||||
backdropPath?: string;
|
backdropPath?: string;
|
||||||
posterPath?: string;
|
posterPath?: string;
|
||||||
|
contentRatings: TmdbTvRatingResult;
|
||||||
createdBy: {
|
createdBy: {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -174,6 +176,7 @@ export const mapTvDetails = (
|
|||||||
originCountry: company.origin_country,
|
originCountry: company.origin_country,
|
||||||
logoPath: company.logo_path,
|
logoPath: company.logo_path,
|
||||||
})),
|
})),
|
||||||
|
contentRatings: show.content_ratings,
|
||||||
spokenLanguages: show.spoken_languages.map((language) => ({
|
spokenLanguages: show.spoken_languages.map((language) => ({
|
||||||
englishName: language.english_name,
|
englishName: language.english_name,
|
||||||
iso_639_1: language.iso_639_1,
|
iso_639_1: language.iso_639_1,
|
||||||
|
@@ -129,7 +129,22 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
|
|||||||
revalidate();
|
revalidate();
|
||||||
};
|
};
|
||||||
|
|
||||||
const movieAttributes = [];
|
const movieAttributes: React.ReactNode[] = [];
|
||||||
|
|
||||||
|
if (
|
||||||
|
data.releases.results.length &&
|
||||||
|
(data.releases.results.find((r) => r.iso_3166_1 === 'US')?.release_dates[0]
|
||||||
|
.certification ||
|
||||||
|
data.releases.results[0].release_dates[0].certification)
|
||||||
|
) {
|
||||||
|
movieAttributes.push(
|
||||||
|
<span className="p-0.5 py-0 border rounded-md">
|
||||||
|
{data.releases.results.find((r) => r.iso_3166_1 === 'US')
|
||||||
|
?.release_dates[0].certification ||
|
||||||
|
data.releases.results[0].release_dates[0].certification}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (data.runtime) {
|
if (data.runtime) {
|
||||||
movieAttributes.push(
|
movieAttributes.push(
|
||||||
@@ -369,7 +384,13 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
|
|||||||
)}
|
)}
|
||||||
</h1>
|
</h1>
|
||||||
<span className="mt-1 text-xs lg:text-base lg:mt-0">
|
<span className="mt-1 text-xs lg:text-base lg:mt-0">
|
||||||
{movieAttributes.join(' | ')}
|
{movieAttributes
|
||||||
|
.map((t, k) => <span key={k}>{t}</span>)
|
||||||
|
.reduce((prev, curr) => (
|
||||||
|
<>
|
||||||
|
{prev} | {curr}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative z-10 flex flex-wrap justify-center flex-shrink-0 mt-4 sm:justify-end sm:flex-nowrap lg:mt-0">
|
<div className="relative z-10 flex flex-wrap justify-center flex-shrink-0 mt-4 sm:justify-end sm:flex-nowrap lg:mt-0">
|
||||||
|
@@ -133,6 +133,26 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
|
|||||||
revalidate();
|
revalidate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const seriesAttributes: React.ReactNode[] = [];
|
||||||
|
|
||||||
|
if (
|
||||||
|
data.contentRatings.results.length &&
|
||||||
|
data.contentRatings.results.find(
|
||||||
|
(r) => r.iso_3166_1 === 'US' || data.contentRatings.results[0].rating
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
seriesAttributes.push(
|
||||||
|
<span className="p-0.5 py-0 border rounded-md">
|
||||||
|
{data.contentRatings.results.find((r) => r.iso_3166_1 === 'US')
|
||||||
|
?.rating || data.contentRatings.results[0].rating}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.genres.length) {
|
||||||
|
seriesAttributes.push(data.genres.map((g) => g.name).join(', '));
|
||||||
|
}
|
||||||
|
|
||||||
const isComplete =
|
const isComplete =
|
||||||
data.seasons.filter((season) => season.seasonNumber !== 0).length <=
|
data.seasons.filter((season) => season.seasonNumber !== 0).length <=
|
||||||
(
|
(
|
||||||
@@ -392,7 +412,13 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
|
|||||||
)}
|
)}
|
||||||
</h1>
|
</h1>
|
||||||
<span className="mt-1 text-xs lg:text-base lg:mt-0">
|
<span className="mt-1 text-xs lg:text-base lg:mt-0">
|
||||||
{data.genres.map((g) => g.name).join(', ')}
|
{seriesAttributes
|
||||||
|
.map((t, k) => <span key={k}>{t}</span>)
|
||||||
|
.reduce((prev, curr) => (
|
||||||
|
<>
|
||||||
|
{prev} | {curr}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap justify-center flex-shrink-0 mt-4 sm:flex-nowrap sm:justify-end lg:mt-0">
|
<div className="flex flex-wrap justify-center flex-shrink-0 mt-4 sm:flex-nowrap sm:justify-end lg:mt-0">
|
||||||
|
Reference in New Issue
Block a user