1
0
mirror of https://github.com/Radarr/Radarr.git synced 2024-10-02 14:17:19 +02:00

Fixed: Improve appearance and sorting by ratings for Discover

Fixes #7271
This commit is contained in:
Bogdan 2024-08-25 09:22:23 +03:00
parent d79db69644
commit 2ba4562f49
20 changed files with 419 additions and 149 deletions

View File

@ -56,15 +56,6 @@ function DiscoverMovieSortMenu(props) {
{translate('InCinemas')} {translate('InCinemas')}
</SortMenuItem> </SortMenuItem>
<SortMenuItem
name="physicalRelease"
sortKey={sortKey}
sortDirection={sortDirection}
onPress={onSortSelect}
>
{translate('PhysicalRelease')}
</SortMenuItem>
<SortMenuItem <SortMenuItem
name="digitalRelease" name="digitalRelease"
sortKey={sortKey} sortKey={sortKey}
@ -74,6 +65,15 @@ function DiscoverMovieSortMenu(props) {
{translate('DigitalRelease')} {translate('DigitalRelease')}
</SortMenuItem> </SortMenuItem>
<SortMenuItem
name="physicalRelease"
sortKey={sortKey}
sortDirection={sortDirection}
onPress={onSortSelect}
>
{translate('PhysicalRelease')}
</SortMenuItem>
<SortMenuItem <SortMenuItem
name="runtime" name="runtime"
sortKey={sortKey} sortKey={sortKey}
@ -84,12 +84,30 @@ function DiscoverMovieSortMenu(props) {
</SortMenuItem> </SortMenuItem>
<SortMenuItem <SortMenuItem
name="ratings" name="tmdbRating"
sortKey={sortKey} sortKey={sortKey}
sortDirection={sortDirection} sortDirection={sortDirection}
onPress={onSortSelect} onPress={onSortSelect}
> >
{translate('Rating')} {translate('TmdbRating')}
</SortMenuItem>
<SortMenuItem
name="imdbRating"
sortKey={sortKey}
sortDirection={sortDirection}
onPress={onSortSelect}
>
{translate('ImdbRating')}
</SortMenuItem>
<SortMenuItem
name="rottenTomatoesRating"
sortKey={sortKey}
sortDirection={sortDirection}
onPress={onSortSelect}
>
{translate('RottenTomatoesRating')}
</SortMenuItem> </SortMenuItem>
<SortMenuItem <SortMenuItem

View File

@ -1,3 +1,4 @@
import _ from 'lodash';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import { icons } from 'Helpers/Props'; import { icons } from 'Helpers/Props';
@ -14,25 +15,30 @@ const rows = [
showProp: 'showYear', showProp: 'showYear',
valueProp: 'year' valueProp: 'year'
}, },
{
name: 'studio',
showProp: 'showStudio',
valueProp: 'studio'
},
{ {
name: 'genres', name: 'genres',
showProp: 'showGenres', showProp: 'showGenres',
valueProp: 'genres' valueProp: 'genres'
}, },
{ {
name: 'ratings', name: 'tmdbRating',
showProp: 'showRatings', showProp: 'showTmdbRating',
valueProp: 'ratings' valueProp: 'ratings.tmdb.value'
},
{
name: 'imdbRating',
showProp: 'showImdbRating',
valueProp: 'ratings.imdb.value'
}, },
{ {
name: 'certification', name: 'certification',
showProp: 'showCertification', showProp: 'showCertification',
valueProp: 'certification' valueProp: 'certification'
},
{
name: 'studio',
showProp: 'showStudio',
valueProp: 'studio'
} }
]; ];
@ -43,11 +49,7 @@ function isVisible(row, props) {
valueProp valueProp
} = row; } = row;
if (props[valueProp] == null) { return _.has(props, valueProp) && (_.get(props, showProp) || props.sortKey === name);
return false;
}
return props[showProp] || props.sortKey === name;
} }
function getInfoRowProps(row, props) { function getInfoRowProps(row, props) {
@ -61,6 +63,14 @@ function getInfoRowProps(row, props) {
}; };
} }
if (name === 'studio') {
return {
title: translate('Studio'),
iconName: icons.STUDIO,
label: props.studio
};
}
if (name === 'genres') { if (name === 'genres') {
return { return {
title: translate('Genres'), title: translate('Genres'),
@ -69,14 +79,22 @@ function getInfoRowProps(row, props) {
}; };
} }
if (name === 'ratings') { if (name === 'tmdbRating' && !!props.ratings.tmdb) {
return { return {
title: translate('Ratings'), title: translate('TmdbRating'),
iconName: icons.HEART, iconName: icons.HEART,
label: `${(props.ratings.tmdb.value * 10).toFixed()}%` label: `${(props.ratings.tmdb.value * 10).toFixed()}%`
}; };
} }
if (name === 'imdbRating' && !!props.ratings.imdb) {
return {
title: translate('ImdbRating'),
iconName: icons.IMDB,
label: `${(props.ratings.imdb.value).toFixed(1)}`
};
}
if (name === 'certification') { if (name === 'certification') {
return { return {
title: translate('Certification'), title: translate('Certification'),
@ -84,14 +102,6 @@ function getInfoRowProps(row, props) {
label: props.certification label: props.certification
}; };
} }
if (name === 'studio') {
return {
title: translate('Studio'),
iconName: icons.STUDIO,
label: props.studio
};
}
} }
function DiscoverMovieOverviewInfo(props) { function DiscoverMovieOverviewInfo(props) {
@ -132,11 +142,12 @@ function DiscoverMovieOverviewInfo(props) {
DiscoverMovieOverviewInfo.propTypes = { DiscoverMovieOverviewInfo.propTypes = {
height: PropTypes.number.isRequired, height: PropTypes.number.isRequired,
showStudio: PropTypes.bool.isRequired,
showYear: PropTypes.bool.isRequired, showYear: PropTypes.bool.isRequired,
showRatings: PropTypes.bool.isRequired, showStudio: PropTypes.bool.isRequired,
showCertification: PropTypes.bool.isRequired,
showGenres: PropTypes.bool.isRequired, showGenres: PropTypes.bool.isRequired,
showTmdbRating: PropTypes.bool.isRequired,
showImdbRating: PropTypes.bool.isRequired,
showCertification: PropTypes.bool.isRequired,
studio: PropTypes.string, studio: PropTypes.string,
year: PropTypes.number, year: PropTypes.number,
certification: PropTypes.string, certification: PropTypes.string,

View File

@ -1,35 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import Icon from 'Components/Icon';
import styles from './DiscoverMovieOverviewInfoRow.css';
function DiscoverMovieOverviewInfoRow(props) {
const {
title,
iconName,
label
} = props;
return (
<div
className={styles.infoRow}
title={title}
>
<Icon
className={styles.icon}
name={iconName}
size={14}
/>
{label}
</div>
);
}
DiscoverMovieOverviewInfoRow.propTypes = {
title: PropTypes.string,
iconName: PropTypes.object.isRequired,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
};
export default DiscoverMovieOverviewInfoRow;

View File

@ -0,0 +1,26 @@
import { IconDefinition } from '@fortawesome/free-regular-svg-icons';
import React from 'react';
import Icon from 'Components/Icon';
import styles from './DiscoverMovieOverviewInfoRow.css';
interface DiscoverMovieOverviewInfoRowProps {
title?: string;
iconName?: IconDefinition;
label: string | null;
}
function DiscoverMovieOverviewInfoRow(
props: DiscoverMovieOverviewInfoRowProps
) {
const { title, iconName, label } = props;
return (
<div className={styles.infoRow} title={title}>
<Icon className={styles.icon} name={iconName} size={14} />
{label}
</div>
);
}
export default DiscoverMovieOverviewInfoRow;

View File

@ -65,7 +65,8 @@ class DiscoverMovieOverviews extends Component {
items, items,
sortKey, sortKey,
overviewOptions, overviewOptions,
jumpToCharacter jumpToCharacter,
isSmallScreen
} = this.props; } = this.props;
const { const {
@ -75,13 +76,17 @@ class DiscoverMovieOverviews extends Component {
if (prevProps.sortKey !== sortKey || if (prevProps.sortKey !== sortKey ||
prevProps.overviewOptions !== overviewOptions) { prevProps.overviewOptions !== overviewOptions) {
this.calculateGrid(); this.calculateGrid(this.state.width, isSmallScreen);
} }
if (this._grid && if (
this._grid &&
(prevState.width !== width || (prevState.width !== width ||
prevState.rowHeight !== rowHeight || prevState.rowHeight !== rowHeight ||
hasDifferentItemsOrOrder(prevProps.items, items, 'tmdbId'))) { hasDifferentItemsOrOrder(prevProps.items, items, 'tmdbId') ||
prevProps.overviewOptions !== overviewOptions
)
) {
// recomputeGridSize also forces Grid to discard its cache of rendered cells // recomputeGridSize also forces Grid to discard its cache of rendered cells
this._grid.recomputeGridSize(); this._grid.recomputeGridSize();
} }

View File

@ -44,11 +44,12 @@ class DiscoverMovieOverviewOptionsModalContent extends Component {
this.state = { this.state = {
size: props.size, size: props.size,
showStudio: props.showStudio,
showCertification: props.showCertification,
showRatings: props.showRatings,
showYear: props.showYear, showYear: props.showYear,
showStudio: props.showStudio,
showGenres: props.showGenres, showGenres: props.showGenres,
showTmdbRating: props.showTmdbRating,
showImdbRating: props.showImdbRating,
showCertification: props.showCertification,
includeRecommendations: props.includeRecommendations, includeRecommendations: props.includeRecommendations,
includeTrending: props.includeTrending, includeTrending: props.includeTrending,
includePopular: props.includePopular includePopular: props.includePopular
@ -58,11 +59,12 @@ class DiscoverMovieOverviewOptionsModalContent extends Component {
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
const { const {
size, size,
showStudio,
showYear, showYear,
showRatings, showStudio,
showCertification,
showGenres, showGenres,
showTmdbRating,
showImdbRating,
showCertification,
includeRecommendations, includeRecommendations,
includeTrending, includeTrending,
includePopular includePopular
@ -74,26 +76,30 @@ class DiscoverMovieOverviewOptionsModalContent extends Component {
state.size = size; state.size = size;
} }
if (showStudio !== prevProps.showStudio) {
state.showStudio = showStudio;
}
if (showYear !== prevProps.showYear) { if (showYear !== prevProps.showYear) {
state.showYear = showYear; state.showYear = showYear;
} }
if (showRatings !== prevProps.showRatings) { if (showStudio !== prevProps.showStudio) {
state.showRatings = showRatings; state.showStudio = showStudio;
}
if (showCertification !== prevProps.showCertification) {
state.showCertification = showCertification;
} }
if (showGenres !== prevProps.showGenres) { if (showGenres !== prevProps.showGenres) {
state.showGenres = showGenres; state.showGenres = showGenres;
} }
if (showTmdbRating !== prevProps.showTmdbRating) {
state.showTmdbRating = showTmdbRating;
}
if (showImdbRating !== prevProps.showImdbRating) {
state.showImdbRating = showImdbRating;
}
if (showCertification !== prevProps.showCertification) {
state.showCertification = showCertification;
}
if (includeRecommendations !== prevProps.includeRecommendations) { if (includeRecommendations !== prevProps.includeRecommendations) {
state.includeRecommendations = includeRecommendations; state.includeRecommendations = includeRecommendations;
} }
@ -142,11 +148,12 @@ class DiscoverMovieOverviewOptionsModalContent extends Component {
const { const {
size, size,
showStudio,
showCertification,
showRatings,
showYear, showYear,
showStudio,
showGenres, showGenres,
showTmdbRating,
showImdbRating,
showCertification,
includeRecommendations, includeRecommendations,
includeTrending, includeTrending,
includePopular includePopular
@ -209,12 +216,12 @@ class DiscoverMovieOverviewOptionsModalContent extends Component {
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<FormLabel>{translate('ShowGenres')}</FormLabel> <FormLabel>{translate('ShowYear')}</FormLabel>
<FormInputGroup <FormInputGroup
type={inputTypes.CHECK} type={inputTypes.CHECK}
name="showGenres" name="showYear"
value={showGenres} value={showYear}
onChange={this.onChangeOverviewOption} onChange={this.onChangeOverviewOption}
/> />
</FormGroup> </FormGroup>
@ -231,23 +238,34 @@ class DiscoverMovieOverviewOptionsModalContent extends Component {
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<FormLabel>{translate('ShowYear')}</FormLabel> <FormLabel>{translate('ShowGenres')}</FormLabel>
<FormInputGroup <FormInputGroup
type={inputTypes.CHECK} type={inputTypes.CHECK}
name="showYear" name="showGenres"
value={showYear} value={showGenres}
onChange={this.onChangeOverviewOption} onChange={this.onChangeOverviewOption}
/> />
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<FormLabel>{translate('ShowRatings')}</FormLabel> <FormLabel>{translate('ShowTmdbRating')}</FormLabel>
<FormInputGroup <FormInputGroup
type={inputTypes.CHECK} type={inputTypes.CHECK}
name="showRatings" name="showTmdbRating"
value={showRatings} value={showTmdbRating}
onChange={this.onChangeOverviewOption}
/>
</FormGroup>
<FormGroup>
<FormLabel>{translate('ShowImdbRating')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="showImdbRating"
value={showImdbRating}
onChange={this.onChangeOverviewOption} onChange={this.onChangeOverviewOption}
/> />
</FormGroup> </FormGroup>
@ -279,11 +297,12 @@ class DiscoverMovieOverviewOptionsModalContent extends Component {
DiscoverMovieOverviewOptionsModalContent.propTypes = { DiscoverMovieOverviewOptionsModalContent.propTypes = {
size: PropTypes.string.isRequired, size: PropTypes.string.isRequired,
showStudio: PropTypes.bool.isRequired,
showYear: PropTypes.bool.isRequired, showYear: PropTypes.bool.isRequired,
showRatings: PropTypes.bool.isRequired, showStudio: PropTypes.bool.isRequired,
showCertification: PropTypes.bool.isRequired,
showGenres: PropTypes.bool.isRequired, showGenres: PropTypes.bool.isRequired,
showTmdbRating: PropTypes.bool.isRequired,
showImdbRating: PropTypes.bool.isRequired,
showCertification: PropTypes.bool.isRequired,
includeRecommendations: PropTypes.bool.isRequired, includeRecommendations: PropTypes.bool.isRequired,
includeTrending: PropTypes.bool.isRequired, includeTrending: PropTypes.bool.isRequired,
includePopular: PropTypes.bool.isRequired, includePopular: PropTypes.bool.isRequired,

View File

@ -2,9 +2,12 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import CheckInput from 'Components/Form/CheckInput'; import CheckInput from 'Components/Form/CheckInput';
import Icon from 'Components/Icon'; import Icon from 'Components/Icon';
import ImdbRating from 'Components/ImdbRating';
import Label from 'Components/Label'; import Label from 'Components/Label';
import IconButton from 'Components/Link/IconButton'; import IconButton from 'Components/Link/IconButton';
import Link from 'Components/Link/Link'; import Link from 'Components/Link/Link';
import RottenTomatoRating from 'Components/RottenTomatoRating';
import TmdbRating from 'Components/TmdbRating';
import Popover from 'Components/Tooltip/Popover'; import Popover from 'Components/Tooltip/Popover';
import AddNewDiscoverMovieModal from 'DiscoverMovie/AddNewDiscoverMovieModal'; import AddNewDiscoverMovieModal from 'DiscoverMovie/AddNewDiscoverMovieModal';
import ExcludeMovieModal from 'DiscoverMovie/Exclusion/ExcludeMovieModal'; import ExcludeMovieModal from 'DiscoverMovie/Exclusion/ExcludeMovieModal';
@ -86,6 +89,10 @@ class DiscoverMoviePoster extends Component {
posterWidth, posterWidth,
posterHeight, posterHeight,
showTitle, showTitle,
showTmdbRating,
showImdbRating,
showRottenTomatoesRating,
ratings,
isExisting, isExisting,
isExcluded, isExcluded,
isSelected, isSelected,
@ -192,18 +199,39 @@ class DiscoverMoviePoster extends Component {
</Link> </Link>
</div> </div>
{ {showTitle ?
showTitle &&
<div className={styles.title} title={title}> <div className={styles.title} title={title}>
{title} {title}
</div> :
null}
{showTmdbRating && !!ratings.tmdb ? (
<div className={styles.title}>
<TmdbRating ratings={ratings} iconSize={12} />
</div> </div>
} ) : null}
{showImdbRating && !!ratings.imdb ? (
<div className={styles.title}>
<ImdbRating ratings={ratings} iconSize={12} />
</div>
) : null}
{showRottenTomatoesRating && !!ratings.rottenTomatoes ? (
<div className={styles.title}>
<RottenTomatoRating ratings={ratings} iconSize={12} />
</div>
) : null}
<DiscoverMoviePosterInfo <DiscoverMoviePosterInfo
showRelativeDates={showRelativeDates} showRelativeDates={showRelativeDates}
shortDateFormat={shortDateFormat} shortDateFormat={shortDateFormat}
timeFormat={timeFormat} timeFormat={timeFormat}
movieRuntimeFormat={movieRuntimeFormat} movieRuntimeFormat={movieRuntimeFormat}
ratings={ratings}
showTmdbRating={showTmdbRating}
showImdbRating={showImdbRating}
showRottenTomatoesRating={showRottenTomatoesRating}
{...otherProps} {...otherProps}
/> />
@ -243,6 +271,10 @@ DiscoverMoviePoster.propTypes = {
posterWidth: PropTypes.number.isRequired, posterWidth: PropTypes.number.isRequired,
posterHeight: PropTypes.number.isRequired, posterHeight: PropTypes.number.isRequired,
showTitle: PropTypes.bool.isRequired, showTitle: PropTypes.bool.isRequired,
showTmdbRating: PropTypes.bool.isRequired,
showImdbRating: PropTypes.bool.isRequired,
showRottenTomatoesRating: PropTypes.bool.isRequired,
ratings: PropTypes.object.isRequired,
showRelativeDates: PropTypes.bool.isRequired, showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired, shortDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired, timeFormat: PropTypes.string.isRequired,

View File

@ -1,6 +1,8 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import Icon from 'Components/Icon'; import Icon from 'Components/Icon';
import ImdbRating from 'Components/ImdbRating';
import RottenTomatoRating from 'Components/RottenTomatoRating';
import TmdbRating from 'Components/TmdbRating'; import TmdbRating from 'Components/TmdbRating';
import { icons } from 'Helpers/Props'; import { icons } from 'Helpers/Props';
import getMovieStatusDetails from 'Movie/getMovieStatusDetails'; import getMovieStatusDetails from 'Movie/getMovieStatusDetails';
@ -23,7 +25,10 @@ function DiscoverMoviePosterInfo(props) {
showRelativeDates, showRelativeDates,
shortDateFormat, shortDateFormat,
timeFormat, timeFormat,
movieRuntimeFormat movieRuntimeFormat,
showTmdbRating,
showImdbRating,
showRottenTomatoesRating
} = props; } = props;
if (sortKey === 'status' && status) { if (sortKey === 'status' && status) {
@ -112,10 +117,26 @@ function DiscoverMoviePosterInfo(props) {
); );
} }
if (sortKey === 'ratings' && ratings) { if (!showTmdbRating && sortKey === 'tmdbRating' && !!ratings.tmdb) {
return ( return (
<div className={styles.info}> <div className={styles.info}>
<TmdbRating ratings={ratings} /> <TmdbRating ratings={ratings} iconSize={12} />
</div>
);
}
if (!showImdbRating && sortKey === 'imdbRating' && !!ratings.imdb) {
return (
<div className={styles.info}>
<ImdbRating ratings={ratings} iconSize={12} />
</div>
);
}
if (!showRottenTomatoesRating && sortKey === 'rottenTomatoesRating' && !!ratings.rottenTomatoes) {
return (
<div className={styles.info}>
<RottenTomatoRating ratings={ratings} iconSize={12} />
</div> </div>
); );
} }
@ -136,7 +157,10 @@ DiscoverMoviePosterInfo.propTypes = {
showRelativeDates: PropTypes.bool.isRequired, showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired, shortDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired, timeFormat: PropTypes.string.isRequired,
movieRuntimeFormat: PropTypes.string.isRequired movieRuntimeFormat: PropTypes.string.isRequired,
showTmdbRating: PropTypes.bool.isRequired,
showImdbRating: PropTypes.bool.isRequired,
showRottenTomatoesRating: PropTypes.bool.isRequired
}; };
export default DiscoverMoviePosterInfo; export default DiscoverMoviePosterInfo;

View File

@ -36,15 +36,15 @@ function calculateColumnWidth(width, posterSize, isSmallScreen) {
function calculateRowHeight(posterHeight, sortKey, isSmallScreen, posterOptions) { function calculateRowHeight(posterHeight, sortKey, isSmallScreen, posterOptions) {
const { const {
detailedProgressBar, detailedProgressBar,
showTitle showTitle,
showTmdbRating,
showImdbRating,
showRottenTomatoesRating
} = posterOptions; } = posterOptions;
const nextAiringHeight = 19;
const heights = [ const heights = [
posterHeight, posterHeight,
detailedProgressBar ? detailedProgressBarHeight : progressBarHeight, detailedProgressBar ? detailedProgressBarHeight : progressBarHeight,
nextAiringHeight,
isSmallScreen ? columnPaddingSmallScreen : columnPadding isSmallScreen ? columnPaddingSmallScreen : columnPadding
]; ];
@ -52,8 +52,42 @@ function calculateRowHeight(posterHeight, sortKey, isSmallScreen, posterOptions)
heights.push(19); heights.push(19);
} }
if (showTmdbRating) {
heights.push(19);
}
if (showImdbRating) {
heights.push(19);
}
if (showRottenTomatoesRating) {
heights.push(19);
}
switch (sortKey) { switch (sortKey) {
case 'studio': case 'studio':
case 'inCinemas':
case 'digitalRelease':
case 'physicalRelease':
case 'runtime':
case 'certification':
heights.push(19);
break;
case 'tmdbRating':
if (!showTmdbRating) {
heights.push(19);
}
break;
case 'imdbRating':
if (!showImdbRating) {
heights.push(19);
}
break;
case 'rottenTomatoesRating':
if (!showRottenTomatoesRating) {
heights.push(19);
}
break;
default: default:
// No need to add a height of 0 // No need to add a height of 0
} }
@ -182,7 +216,10 @@ class DiscoverMoviePosters extends Component {
} = this.state; } = this.state;
const { const {
showTitle showTitle,
showTmdbRating,
showImdbRating,
showRottenTomatoesRating
} = posterOptions; } = posterOptions;
const movieIdx = rowIndex * columnCount + columnIndex; const movieIdx = rowIndex * columnCount + columnIndex;
@ -208,6 +245,9 @@ class DiscoverMoviePosters extends Component {
posterWidth={posterWidth} posterWidth={posterWidth}
posterHeight={posterHeight} posterHeight={posterHeight}
showTitle={showTitle} showTitle={showTitle}
showTmdbRating={showTmdbRating}
showImdbRating={showImdbRating}
showRottenTomatoesRating={showRottenTomatoesRating}
showRelativeDates={showRelativeDates} showRelativeDates={showRelativeDates}
shortDateFormat={shortDateFormat} shortDateFormat={shortDateFormat}
timeFormat={timeFormat} timeFormat={timeFormat}

View File

@ -45,6 +45,9 @@ class DiscoverMoviePosterOptionsModalContent extends Component {
this.state = { this.state = {
size: props.size, size: props.size,
showTitle: props.showTitle, showTitle: props.showTitle,
showTmdbRating: props.showTmdbRating,
showImdbRating: props.showImdbRating,
showRottenTomatoesRating: props.showRottenTomatoesRating,
includeRecommendations: props.includeRecommendations, includeRecommendations: props.includeRecommendations,
includeTrending: props.includeTrending, includeTrending: props.includeTrending,
includePopular: props.includePopular includePopular: props.includePopular
@ -55,6 +58,9 @@ class DiscoverMoviePosterOptionsModalContent extends Component {
const { const {
size, size,
showTitle, showTitle,
showTmdbRating,
showImdbRating,
showRottenTomatoesRating,
includeRecommendations, includeRecommendations,
includeTrending, includeTrending,
includePopular includePopular
@ -70,6 +76,18 @@ class DiscoverMoviePosterOptionsModalContent extends Component {
state.showTitle = showTitle; state.showTitle = showTitle;
} }
if (showTmdbRating !== prevProps.showTmdbRating) {
state.showTmdbRating = showTmdbRating;
}
if (showImdbRating !== prevProps.showImdbRating) {
state.showImdbRating = showImdbRating;
}
if (showRottenTomatoesRating !== prevProps.showRottenTomatoesRating) {
state.showRottenTomatoesRating = showRottenTomatoesRating;
}
if (includeRecommendations !== prevProps.includeRecommendations) { if (includeRecommendations !== prevProps.includeRecommendations) {
state.includeRecommendations = includeRecommendations; state.includeRecommendations = includeRecommendations;
} }
@ -119,6 +137,9 @@ class DiscoverMoviePosterOptionsModalContent extends Component {
const { const {
size, size,
showTitle, showTitle,
showTmdbRating,
showImdbRating,
showRottenTomatoesRating,
includeRecommendations, includeRecommendations,
includeTrending, includeTrending,
includePopular includePopular
@ -191,6 +212,42 @@ class DiscoverMoviePosterOptionsModalContent extends Component {
onChange={this.onChangePosterOption} onChange={this.onChangePosterOption}
/> />
</FormGroup> </FormGroup>
<FormGroup>
<FormLabel>{translate('ShowTmdbRating')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="showTmdbRating"
value={showTmdbRating}
helpText={translate('ShowTmdbRatingHelpText')}
onChange={this.onChangePosterOption}
/>
</FormGroup>
<FormGroup>
<FormLabel>{translate('ShowImdbRating')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="showImdbRating"
value={showImdbRating}
helpText={translate('ShowImdbRatingHelpText')}
onChange={this.onChangePosterOption}
/>
</FormGroup>
<FormGroup>
<FormLabel>{translate('ShowRottenTomatoesRating')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="showRottenTomatoesRating"
value={showRottenTomatoesRating}
helpText={translate('ShowRottenTomatoesRatingHelpText')}
onChange={this.onChangePosterOption}
/>
</FormGroup>
</Form> </Form>
</ModalBody> </ModalBody>
@ -209,6 +266,9 @@ class DiscoverMoviePosterOptionsModalContent extends Component {
DiscoverMoviePosterOptionsModalContent.propTypes = { DiscoverMoviePosterOptionsModalContent.propTypes = {
size: PropTypes.string.isRequired, size: PropTypes.string.isRequired,
showTitle: PropTypes.bool.isRequired, showTitle: PropTypes.bool.isRequired,
showTmdbRating: PropTypes.bool.isRequired,
showImdbRating: PropTypes.bool.isRequired,
showRottenTomatoesRating: PropTypes.bool.isRequired,
includeRecommendations: PropTypes.bool.isRequired, includeRecommendations: PropTypes.bool.isRequired,
includeTrending: PropTypes.bool.isRequired, includeTrending: PropTypes.bool.isRequired,
includePopular: PropTypes.bool.isRequired, includePopular: PropTypes.bool.isRequired,

View File

@ -32,7 +32,9 @@
flex: 1 0 125px; flex: 1 0 125px;
} }
.ratings, .tmdbRating,
.imdbRating,
.rottenTomatoesRating,
.runtime { .runtime {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';

View File

@ -6,6 +6,7 @@ interface CssExports {
'collection': string; 'collection': string;
'digitalRelease': string; 'digitalRelease': string;
'genres': string; 'genres': string;
'imdbRating': string;
'inCinemas': string; 'inCinemas': string;
'isPopular': string; 'isPopular': string;
'isRecommendation': string; 'isRecommendation': string;
@ -14,11 +15,12 @@ interface CssExports {
'originalLanguage': string; 'originalLanguage': string;
'physicalRelease': string; 'physicalRelease': string;
'popularity': string; 'popularity': string;
'ratings': string; 'rottenTomatoesRating': string;
'runtime': string; 'runtime': string;
'sortTitle': string; 'sortTitle': string;
'status': string; 'status': string;
'studio': string; 'studio': string;
'tmdbRating': string;
} }
export const cssExports: CssExports; export const cssExports: CssExports;
export default cssExports; export default cssExports;

View File

@ -57,7 +57,9 @@
flex: 1 0 125px; flex: 1 0 125px;
} }
.ratings, .tmdbRating,
.imdbRating,
.rottenTomatoesRating,
.runtime { .runtime {
composes: cell; composes: cell;

View File

@ -11,6 +11,7 @@ interface CssExports {
'exclusionIcon': string; 'exclusionIcon': string;
'externalLinks': string; 'externalLinks': string;
'genres': string; 'genres': string;
'imdbRating': string;
'inCinemas': string; 'inCinemas': string;
'isPopular': string; 'isPopular': string;
'isRecommendation': string; 'isRecommendation': string;
@ -19,12 +20,13 @@ interface CssExports {
'originalLanguage': string; 'originalLanguage': string;
'physicalRelease': string; 'physicalRelease': string;
'popularity': string; 'popularity': string;
'ratings': string; 'rottenTomatoesRating': string;
'runtime': string; 'runtime': string;
'sortTitle': string; 'sortTitle': string;
'status': string; 'status': string;
'statusIcon': string; 'statusIcon': string;
'studio': string; 'studio': string;
'tmdbRating': string;
} }
export const cssExports: CssExports; export const cssExports: CssExports;
export default cssExports; export default cssExports;

View File

@ -1,9 +1,11 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import Icon from 'Components/Icon'; import Icon from 'Components/Icon';
import ImdbRating from 'Components/ImdbRating';
import ImportListListConnector from 'Components/ImportListListConnector'; import ImportListListConnector from 'Components/ImportListListConnector';
import IconButton from 'Components/Link/IconButton'; import IconButton from 'Components/Link/IconButton';
import Link from 'Components/Link/Link'; import Link from 'Components/Link/Link';
import RottenTomatoRating from 'Components/RottenTomatoRating';
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector'; import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell'; import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell'; import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell';
@ -253,15 +255,35 @@ class DiscoverMovieRow extends Component {
); );
} }
if (name === 'ratings') { if (name === 'tmdbRating') {
return ( return (
<VirtualTableRowCell <VirtualTableRowCell
key={name} key={name}
className={styles[name]} className={styles[name]}
> >
<TmdbRating {ratings.tmdb ? <TmdbRating ratings={ratings} /> : null}
ratings={ratings} </VirtualTableRowCell>
/> );
}
if (name === 'imdbRating') {
return (
<VirtualTableRowCell
key={name}
className={styles[name]}
>
{ratings.imdb ? <ImdbRating ratings={ratings} /> : null}
</VirtualTableRowCell>
);
}
if (name === 'rottenTomatoesRating') {
return (
<VirtualTableRowCell
key={name}
className={styles[name]}
>
{ratings.rottenTomatoes ? <RottenTomatoRating ratings={ratings} /> : null}
</VirtualTableRowCell> </VirtualTableRowCell>
); );
} }

View File

@ -1,6 +1,10 @@
// //
// Brands
import {
faImdb as fabImdb
} from '@fortawesome/free-brands-svg-icons';
//
// Regular // Regular
import { import {
faBookmark as farBookmark, faBookmark as farBookmark,
faCalendar as farCalendar, faCalendar as farCalendar,
@ -175,6 +179,7 @@ export const HEART = fasHeart;
export const HISTORY = fasHistory; export const HISTORY = fasHistory;
export const HOUSEKEEPING = fasHome; export const HOUSEKEEPING = fasHome;
export const IGNORE = fasTimesCircle; export const IGNORE = fasTimesCircle;
export const IMDB = fabImdb;
export const IN_CINEMAS = fasTicketAlt; export const IN_CINEMAS = fasTicketAlt;
export const INFO = fasInfoCircle; export const INFO = fasInfoCircle;
export const INTERACTIVE = fasUser; export const INTERACTIVE = fasUser;

View File

@ -58,17 +58,20 @@ export const defaultState = {
posterOptions: { posterOptions: {
size: 'large', size: 'large',
showTitle: false showTitle: false,
showTmdbRating: false,
showImdbRating: false,
showRottenTomatoesRating: false
}, },
overviewOptions: { overviewOptions: {
detailedProgressBar: false,
size: 'medium', size: 'medium',
showStudio: true,
showRatings: true,
showYear: true, showYear: true,
showCertification: true, showStudio: true,
showGenres: true showGenres: true,
showTmdbRating: false,
showImdbRating: false,
showCertification: true
}, },
tableOptions: { tableOptions: {
@ -136,14 +139,14 @@ export const defaultState = {
isVisible: true isVisible: true
}, },
{ {
name: 'physicalRelease', name: 'digitalRelease',
label: () => translate('PhysicalRelease'), label: () => translate('DigitalRelease'),
isSortable: true, isSortable: true,
isVisible: false isVisible: false
}, },
{ {
name: 'digitalRelease', name: 'physicalRelease',
label: () => translate('DigitalRelease'), label: () => translate('PhysicalRelease'),
isSortable: true, isSortable: true,
isVisible: false isVisible: false
}, },
@ -160,8 +163,20 @@ export const defaultState = {
isVisible: false isVisible: false
}, },
{ {
name: 'ratings', name: 'tmdbRating',
label: () => translate('Ratings'), label: () => translate('TmdbRating'),
isSortable: true,
isVisible: false
},
{
name: 'imdbRating',
label: () => translate('ImdbRating'),
isSortable: true,
isVisible: false
},
{
name: 'rottenTomatoesRating',
label: () => translate('RottenTomatoesRating'),
isSortable: true, isSortable: true,
isVisible: false isVisible: false
}, },
@ -232,12 +247,6 @@ export const defaultState = {
return studio ? studio.toLowerCase() : ''; return studio ? studio.toLowerCase() : '';
}, },
ratings: function(item) {
const { ratings = {} } = item;
return ratings.tmdb? ratings.tmdb.value : 0;
},
inCinemas: function(item, direction) { inCinemas: function(item, direction) {
if (item.inCinemas) { if (item.inCinemas) {
return moment(item.inCinemas).unix(); return moment(item.inCinemas).unix();
@ -272,6 +281,18 @@ export const defaultState = {
} }
return Number.MAX_VALUE; return Number.MAX_VALUE;
},
tmdbRating: function({ ratings = {} }) {
return ratings.tmdb ? ratings.tmdb.value : 0;
},
imdbRating: function({ ratings = {} }) {
return ratings.imdb ? ratings.imdb.value : 0;
},
rottenTomatoesRating: function({ ratings = {} }) {
return ratings.rottenTomatoes ? ratings.rottenTomatoes.value : -1;
} }
}, },

View File

@ -24,6 +24,7 @@
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "6.4.0", "@fortawesome/fontawesome-free": "6.4.0",
"@fortawesome/fontawesome-svg-core": "6.4.0", "@fortawesome/fontawesome-svg-core": "6.4.0",
"@fortawesome/free-brands-svg-icons": "6.6.0",
"@fortawesome/free-regular-svg-icons": "6.4.0", "@fortawesome/free-regular-svg-icons": "6.4.0",
"@fortawesome/free-solid-svg-icons": "6.4.0", "@fortawesome/free-solid-svg-icons": "6.4.0",
"@fortawesome/react-fontawesome": "0.2.0", "@fortawesome/react-fontawesome": "0.2.0",

View File

@ -244,6 +244,7 @@
"CountDownloadClientsSelected": "{count} download client(s) selected", "CountDownloadClientsSelected": "{count} download client(s) selected",
"CountImportListsSelected": "{count} import list(s) selected", "CountImportListsSelected": "{count} import list(s) selected",
"CountIndexersSelected": "{count} indexer(s) selected", "CountIndexersSelected": "{count} indexer(s) selected",
"CountVotes": "{votes} votes",
"CreateEmptyMovieFolders": "Create empty movie folders", "CreateEmptyMovieFolders": "Create empty movie folders",
"CreateEmptyMovieFoldersHelpText": "Create missing movie folders during disk scan", "CreateEmptyMovieFoldersHelpText": "Create missing movie folders during disk scan",
"CreateGroup": "Create group", "CreateGroup": "Create group",

View File

@ -1111,6 +1111,11 @@
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz#88da2b70d6ca18aaa6ed3687832e11f39e80624b" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz#88da2b70d6ca18aaa6ed3687832e11f39e80624b"
integrity sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ== integrity sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==
"@fortawesome/fontawesome-common-types@6.6.0":
version "6.6.0"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.6.0.tgz#31ab07ca6a06358c5de4d295d4711b675006163f"
integrity sha512-xyX0X9mc0kyz9plIyryrRbl7ngsA9jz77mCZJsUkLl+ZKs0KWObgaEBoSgQiYWAsSmjz/yjl0F++Got0Mdp4Rw==
"@fortawesome/fontawesome-free@6.4.0": "@fortawesome/fontawesome-free@6.4.0":
version "6.4.0" version "6.4.0"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.0.tgz#1ee0c174e472c84b23cb46c995154dc383e3b4fe" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.0.tgz#1ee0c174e472c84b23cb46c995154dc383e3b4fe"
@ -1123,6 +1128,13 @@
dependencies: dependencies:
"@fortawesome/fontawesome-common-types" "6.4.0" "@fortawesome/fontawesome-common-types" "6.4.0"
"@fortawesome/free-brands-svg-icons@6.6.0":
version "6.6.0"
resolved "https://registry.yarnpkg.com/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.6.0.tgz#2797f2cc66d21e7e47fa64e680b8835e8d30e825"
integrity sha512-1MPD8lMNW/earme4OQi1IFHtmHUwAKgghXlNwWi9GO7QkTfD+IIaYpIai4m2YJEzqfEji3jFHX1DZI5pbY/biQ==
dependencies:
"@fortawesome/fontawesome-common-types" "6.6.0"
"@fortawesome/free-regular-svg-icons@6.4.0": "@fortawesome/free-regular-svg-icons@6.4.0":
version "6.4.0" version "6.4.0"
resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.0.tgz#cacc53bd8d832d46feead412d9ea9ce80a55e13a" resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.0.tgz#cacc53bd8d832d46feead412d9ea9ce80a55e13a"