From 89fec7841ca4283f05cce5309b50f384e18f5bb5 Mon Sep 17 00:00:00 2001 From: ta264 Date: Sun, 22 Dec 2019 19:15:32 +0000 Subject: [PATCH] Fixed: Cutoff Status and Filter on MovieIndex --- frontend/src/Movie/MovieQuality.js | 24 ++++++-- frontend/src/Movie/MovieStatus.js | 50 +++------------- frontend/src/Store/Actions/movieActions.js | 14 ++--- src/Radarr.Api.V3/Movies/MovieModule.cs | 23 ++++---- src/Radarr.Api.V3/Movies/MovieResource.cs | 67 ++++++++++++++++++++++ 5 files changed, 116 insertions(+), 62 deletions(-) diff --git a/frontend/src/Movie/MovieQuality.js b/frontend/src/Movie/MovieQuality.js index 105787c96..f54dbea5b 100644 --- a/frontend/src/Movie/MovieQuality.js +++ b/frontend/src/Movie/MovieQuality.js @@ -4,7 +4,7 @@ import formatBytes from 'Utilities/Number/formatBytes'; import { kinds } from 'Helpers/Props'; import Label from 'Components/Label'; -function getTooltip(title, quality, size) { +function getTooltip(title, quality, size, isMonitored, isCutoffNotMet) { const revision = quality.revision; if (revision.real && revision.real > 0) { @@ -19,6 +19,12 @@ function getTooltip(title, quality, size) { title += ` - ${formatBytes(size)}`; } + if (!isMonitored) { + title += ' [Not Monitored]'; + } else if (isCutoffNotMet) { + title += ' [Cutoff Not Met]'; + } + return title; } @@ -28,14 +34,22 @@ function MovieQuality(props) { title, quality, size, + isMonitored, isCutoffNotMet } = props; + let kind = kinds.DEFAULT; + if (!isMonitored) { + kind = kinds.DISABLED; + } else if (isCutoffNotMet) { + kind = kinds.INVERSE; + } + return ( @@ -47,11 +61,13 @@ MovieQuality.propTypes = { title: PropTypes.string, quality: PropTypes.object.isRequired, size: PropTypes.number, + isMonitored: PropTypes.bool, isCutoffNotMet: PropTypes.bool }; MovieQuality.defaultProps = { - title: '' + title: '', + isMonitored: true }; export default MovieQuality; diff --git a/frontend/src/Movie/MovieStatus.js b/frontend/src/Movie/MovieStatus.js index ded493a17..c5a7d277a 100644 --- a/frontend/src/Movie/MovieStatus.js +++ b/frontend/src/Movie/MovieStatus.js @@ -4,28 +4,10 @@ import { icons, kinds, sizes } from 'Helpers/Props'; import Icon from 'Components/Icon'; import ProgressBar from 'Components/ProgressBar'; import QueueDetails from 'Activity/Queue/QueueDetails'; -import formatBytes from 'Utilities/Number/formatBytes'; +import MovieQuality from 'Movie/MovieQuality'; import Label from 'Components/Label'; import styles from './MovieStatus.css'; -function getTooltip(title, quality, size) { - const revision = quality.revision; - - if (revision.real && revision.real > 0) { - title += ' [REAL]'; - } - - if (revision.version && revision.version > 1) { - title += ' [PROPER]'; - } - - if (size) { - title += ` - ${formatBytes(size)}`; - } - - return title; -} - function MovieStatus(props) { const { inCinemas, @@ -76,32 +58,18 @@ function MovieStatus(props) { ); } - if (hasMovieFile && monitored) { - const quality = movieFile.quality; - // TODO: Fix on Backend - // const isCutoffNotMet = movieFile.qualityCutoffNotMet; - - return ( -
- -
- ); - } else if (hasMovieFile && !monitored) { + if (hasMovieFile) { const quality = movieFile.quality; return (
- +
); } diff --git a/frontend/src/Store/Actions/movieActions.js b/frontend/src/Store/Actions/movieActions.js index 3ce665325..43e2375e0 100644 --- a/frontend/src/Store/Actions/movieActions.js +++ b/frontend/src/Store/Actions/movieActions.js @@ -97,7 +97,7 @@ export const filters = [ type: filterTypes.EQUAL }, { - key: 'movieFile.qualityCutoffNotMet', + key: 'qualityCutoffNotMet', value: true, type: filterTypes.EQUAL } @@ -106,12 +106,6 @@ export const filters = [ ]; export const filterPredicates = { - missing: function(item) { - const { statistics = {} } = item; - - return statistics.episodeCount - statistics.episodeFileCount > 0; - }, - added: function(item, filterValue, type) { return dateFilterPredicate(item.added, filterValue, type); }, @@ -128,6 +122,12 @@ export const filterPredicates = { const predicate = filterTypePredicates[type]; return predicate(item.ratings.value * 10, filterValue); + }, + + qualityCutoffNotMet: function(item) { + const { movieFile = {} } = item; + + return movieFile.qualityCutoffNotMet; } }; diff --git a/src/Radarr.Api.V3/Movies/MovieModule.cs b/src/Radarr.Api.V3/Movies/MovieModule.cs index 1fab16bea..a0312d738 100644 --- a/src/Radarr.Api.V3/Movies/MovieModule.cs +++ b/src/Radarr.Api.V3/Movies/MovieModule.cs @@ -3,6 +3,7 @@ using FluentValidation; using Nancy; using NzbDrone.Common.Extensions; using NzbDrone.Core.Datastore.Events; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.MediaCover; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles.Events; @@ -28,20 +29,22 @@ namespace Radarr.Api.V3.Movies { protected readonly IMovieService _moviesService; private readonly IMapCoversToLocal _coverMapper; + private readonly IUpgradableSpecification _qualityUpgradableSpecification; public MovieModule(IBroadcastSignalRMessage signalRBroadcaster, - IMovieService moviesService, - IMapCoversToLocal coverMapper, - RootFolderValidator rootFolderValidator, - MoviePathValidator moviesPathValidator, - MovieExistsValidator moviesExistsValidator, - MovieAncestorValidator moviesAncestorValidator, - ProfileExistsValidator profileExistsValidator, - MovieFolderAsRootFolderValidator movieFolderAsRootFolderValidator) + IMovieService moviesService, + IMapCoversToLocal coverMapper, + IUpgradableSpecification qualityUpgradableSpecification, + RootFolderValidator rootFolderValidator, + MoviePathValidator moviesPathValidator, + MovieExistsValidator moviesExistsValidator, + MovieAncestorValidator moviesAncestorValidator, + ProfileExistsValidator profileExistsValidator, + MovieFolderAsRootFolderValidator movieFolderAsRootFolderValidator) : base(signalRBroadcaster) { _moviesService = moviesService; - + _qualityUpgradableSpecification = qualityUpgradableSpecification; _coverMapper = coverMapper; GetResourceAll = AllMovie; @@ -75,7 +78,7 @@ namespace Radarr.Api.V3.Movies private List AllMovie() { - var moviesResources = _moviesService.GetAllMovies().ToResource(); + var moviesResources = _moviesService.GetAllMovies().ToResource(_qualityUpgradableSpecification); MapCoversToLocal(moviesResources.ToArray()); PopulateAlternateTitles(moviesResources); diff --git a/src/Radarr.Api.V3/Movies/MovieResource.cs b/src/Radarr.Api.V3/Movies/MovieResource.cs index 4fae2d762..42bbbb9c8 100644 --- a/src/Radarr.Api.V3/Movies/MovieResource.cs +++ b/src/Radarr.Api.V3/Movies/MovieResource.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.MediaCover; using NzbDrone.Core.Movies; using Radarr.Api.V3.MovieFiles; @@ -132,6 +133,67 @@ namespace Radarr.Api.V3.Movies }; } + public static MovieResource ToResource(this Movie model, IUpgradableSpecification upgradableSpecification) + { + if (model == null) + { + return null; + } + + long size = model.MovieFile?.Size ?? 0; + MovieFileResource movieFile = model.MovieFile?.ToResource(model, upgradableSpecification); + + return new MovieResource + { + Id = model.Id, + TmdbId = model.TmdbId, + Title = model.Title, + SortTitle = model.SortTitle, + InCinemas = model.InCinemas, + PhysicalRelease = model.PhysicalRelease, + PhysicalReleaseNote = model.PhysicalReleaseNote, + HasFile = model.HasFile, + + SizeOnDisk = size, + Status = model.Status, + Overview = model.Overview, + + Images = model.Images, + + Year = model.Year, + SecondaryYear = model.SecondaryYear, + SecondaryYearSourceId = model.SecondaryYearSourceId, + + Path = model.Path, + QualityProfileId = model.ProfileId, + PathState = model.PathState, + + Monitored = model.Monitored, + MinimumAvailability = model.MinimumAvailability, + + IsAvailable = model.IsAvailable(), + FolderName = model.FolderName(), + + Runtime = model.Runtime, + LastInfoSync = model.LastInfoSync, + CleanTitle = model.CleanTitle, + ImdbId = model.ImdbId, + TitleSlug = model.TitleSlug, + RootFolderPath = model.RootFolderPath, + Certification = model.Certification, + Website = model.Website, + Genres = model.Genres, + Tags = model.Tags, + Added = model.Added, + AddOptions = model.AddOptions, + AlternateTitles = model.AlternativeTitles.ToResource(), + Ratings = model.Ratings, + MovieFile = movieFile, + YouTubeTrailerId = model.YouTubeTrailerId, + Studio = model.Studio + }; + } + public static Movie ToModel(this MovieResource resource) { if (resource == null) @@ -197,6 +259,11 @@ namespace Radarr.Api.V3.Movies return movies.Select(ToResource).ToList(); } + public static List ToResource(this IEnumerable movies, IUpgradableSpecification upgradableSpecification) + { + return movies.ToList().ConvertAll(f => f.ToResource(upgradableSpecification)); + } + public static List ToModel(this IEnumerable resources) { return resources.Select(ToModel).ToList();