Wanted & Missing (#687)

* Remove Season Pass, Update Header name, remove useless function

* Cutoff Tab now works
Devin Buhl 8 years ago committed by GitHub
parent 2af07d7e0d
commit f477c46406

@ -267,6 +267,7 @@
<Compile Include="Wanted\CutoffModule.cs" /> <Compile Include="Wanted\CutoffModule.cs" />
<Compile Include="Wanted\LegacyMissingModule.cs" /> <Compile Include="Wanted\LegacyMissingModule.cs" />
<Compile Include="Wanted\MissingModule.cs" /> <Compile Include="Wanted\MissingModule.cs" />
<Compile Include="Wanted\MovieCutoffModule.cs" />
<Compile Include="Wanted\MovieMissingModule.cs" /> <Compile Include="Wanted\MovieMissingModule.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

@ -0,0 +1,48 @@
using NzbDrone.Api.Movie;
using NzbDrone.Api.Movies;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Datastore;
using NzbDrone.SignalR;
namespace NzbDrone.Api.Wanted
{
public class MovieCutoffModule : NzbDroneRestModuleWithSignalR<MovieResource, Core.Tv.Movie>
{
private readonly IMovieCutoffService _movieCutoffService;
public MovieCutoffModule(IMovieCutoffService movieCutoffService,
IMovieService movieService,
IQualityUpgradableSpecification qualityUpgradableSpecification,
IBroadcastSignalRMessage signalRBroadcaster)
: base(signalRBroadcaster, "wanted/cutoff")
{
_movieCutoffService = movieCutoffService;
GetResourcePaged = GetCutoffUnmetMovies;
}
private PagingResource<MovieResource> GetCutoffUnmetMovies(PagingResource<MovieResource> pagingResource)
{
var pagingSpec = pagingResource.MapToPagingSpec<MovieResource, Core.Tv.Movie>("title", SortDirection.Ascending);
if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false")
{
pagingSpec.FilterExpression = v => v.Monitored == false;
}
else
{
pagingSpec.FilterExpression = v => v.Monitored == true;
}
var resource = ApplyToPage(_movieCutoffService.MoviesWhereCutoffUnmet, pagingSpec, v => MapToResource(v));
return resource;
}
private MovieResource MapToResource(Core.Tv.Movie movie)
{
var resource = movie.ToResource();
return resource;
}
}
}

@ -30,7 +30,7 @@ namespace NzbDrone.Api.Wanted
private PagingResource<MovieResource> GetMissingMovies(PagingResource<MovieResource> pagingResource) private PagingResource<MovieResource> GetMissingMovies(PagingResource<MovieResource> pagingResource)
{ {
var pagingSpec = pagingResource.MapToPagingSpec<MovieResource, Core.Tv.Movie>("physicalRelease", SortDirection.Descending); var pagingSpec = pagingResource.MapToPagingSpec<MovieResource, Core.Tv.Movie>("title", SortDirection.Descending);
if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false") if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false")
{ {
@ -46,13 +46,6 @@ namespace NzbDrone.Api.Wanted
return resource; return resource;
} }
private MovieResource GetMovie(int id)
{
var movie = _movieService.GetMovie(id);
var resource = MapToResource(movie, true);
return resource;
}
private MovieResource MapToResource(Core.Tv.Movie movie, bool includeMovieFile) private MovieResource MapToResource(Core.Tv.Movie movie, bool includeMovieFile)
{ {
var resource = movie.ToResource(); var resource = movie.ToResource();

@ -1164,6 +1164,7 @@
<Compile Include="Tv\Events\SeriesUpdatedEvent.cs" /> <Compile Include="Tv\Events\SeriesUpdatedEvent.cs" />
<Compile Include="Tv\MonitoringOptions.cs" /> <Compile Include="Tv\MonitoringOptions.cs" />
<Compile Include="Tv\MoveSeriesService.cs" /> <Compile Include="Tv\MoveSeriesService.cs" />
<Compile Include="Tv\MovieCutoffService.cs" />
<Compile Include="Tv\Ratings.cs" /> <Compile Include="Tv\Ratings.cs" />
<Compile Include="Tv\RefreshEpisodeService.cs" /> <Compile Include="Tv\RefreshEpisodeService.cs" />
<Compile Include="Tv\RefreshMovieService.cs" /> <Compile Include="Tv\RefreshMovieService.cs" />

@ -0,0 +1,48 @@
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Qualities;
namespace NzbDrone.Core.Tv
{
public interface IMovieCutoffService
{
PagingSpec<Movie> MoviesWhereCutoffUnmet(PagingSpec<Movie> pagingSpec);
}
public class MovieCutoffService : IMovieCutoffService
{
private readonly IMovieRepository _movieRepository;
private readonly IProfileService _profileService;
private readonly Logger _logger;
public MovieCutoffService(IMovieRepository movieRepository, IProfileService profileService, Logger logger)
{
_movieRepository = movieRepository;
_profileService = profileService;
_logger = logger;
}
public PagingSpec<Movie> MoviesWhereCutoffUnmet(PagingSpec<Movie> pagingSpec)
{
var qualitiesBelowCutoff = new List<QualitiesBelowCutoff>();
var profiles = _profileService.All();
//Get all items less than the cutoff
foreach (var profile in profiles)
{
var cutoffIndex = profile.Items.FindIndex(v => v.Quality == profile.Cutoff);
var belowCutoff = profile.Items.Take(cutoffIndex).ToList();
if (belowCutoff.Any())
{
qualitiesBelowCutoff.Add(new QualitiesBelowCutoff(profile.Id, belowCutoff.Select(i => i.Quality.Id)));
}
}
return _movieRepository.MoviesWhereCutoffUnmet(pagingSpec, qualitiesBelowCutoff);
}
}
}

@ -6,6 +6,7 @@ using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Datastore.Extensions; using NzbDrone.Core.Datastore.Extensions;
using Marr.Data.QGen; using Marr.Data.QGen;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Qualities;
namespace NzbDrone.Core.Tv namespace NzbDrone.Core.Tv
{ {
@ -22,6 +23,7 @@ namespace NzbDrone.Core.Tv
PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec); PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec);
List<Movie> GetMoviesByFileId(int fileId); List<Movie> GetMoviesByFileId(int fileId);
void SetFileId(int fileId, int movieId); void SetFileId(int fileId, int movieId);
PagingSpec<Movie> MoviesWhereCutoffUnmet(PagingSpec<Movie> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff);
} }
public class MovieRepository : BasicRepository<Movie>, IMovieRepository public class MovieRepository : BasicRepository<Movie>, IMovieRepository
@ -200,6 +202,41 @@ namespace NzbDrone.Core.Tv
.Take(pagingSpec.PageSize); .Take(pagingSpec.PageSize);
} }
public PagingSpec<Movie> MoviesWhereCutoffUnmet(PagingSpec<Movie> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff)
{
pagingSpec.TotalRecords = MoviesWhereCutoffUnmetQuery(pagingSpec, qualitiesBelowCutoff).GetRowCount();
pagingSpec.Records = MoviesWhereCutoffUnmetQuery(pagingSpec, qualitiesBelowCutoff).ToList();
return pagingSpec;
}
private SortBuilder<Movie> MoviesWhereCutoffUnmetQuery(PagingSpec<Movie> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff)
{
return Query.Join<Movie, MovieFile>(JoinType.Left, e => e.MovieFile, (e, s) => e.MovieFileId == s.Id)
.Where(pagingSpec.FilterExpression)
.AndWhere(m => m.MovieFileId != 0)
.AndWhere(BuildQualityCutoffWhereClause(qualitiesBelowCutoff))
.OrderBy(pagingSpec.OrderByClause(), pagingSpec.ToSortDirection())
.Skip(pagingSpec.PagingOffset())
.Take(pagingSpec.PageSize);
}
private string BuildQualityCutoffWhereClause(List<QualitiesBelowCutoff> qualitiesBelowCutoff)
{
var clauses = new List<string>();
foreach (var profile in qualitiesBelowCutoff)
{
foreach (var belowCutoff in profile.QualityIds)
{
clauses.Add(string.Format("([t0].[ProfileId] = {0} AND [t1].[Quality] LIKE '%_quality_: {1},%')", profile.ProfileId, belowCutoff));
}
}
return string.Format("({0})", string.Join(" OR ", clauses));
}
public Movie FindByTmdbId(int tmdbid) public Movie FindByTmdbId(int tmdbid)
{ {
return Query.Where(m => m.TmdbId == tmdbid).FirstOrDefault(); return Query.Where(m => m.TmdbId == tmdbid).FirstOrDefault();

@ -1,5 +1,5 @@
var _ = require('underscore'); var _ = require('underscore');
var EpisodeModel = require('../../Series/EpisodeModel'); var MovieModel = require('../../Movies/MovieModel');
var PagableCollection = require('backbone.pageable'); var PagableCollection = require('backbone.pageable');
var AsFilteredCollection = require('../../Mixins/AsFilteredCollection'); var AsFilteredCollection = require('../../Mixins/AsFilteredCollection');
var AsSortedCollection = require('../../Mixins/AsSortedCollection'); var AsSortedCollection = require('../../Mixins/AsSortedCollection');
@ -7,13 +7,13 @@ var AsPersistedStateCollection = require('../../Mixins/AsPersistedStateCollectio
var Collection = PagableCollection.extend({ var Collection = PagableCollection.extend({
url : window.NzbDrone.ApiRoot + '/wanted/cutoff', url : window.NzbDrone.ApiRoot + '/wanted/cutoff',
model : EpisodeModel, model : MovieModel,
tableName : 'wanted.cutoff', tableName : 'wanted.cutoff',
state : { state : {
pageSize : 15, pageSize : 15,
sortKey : 'airDateUtc', sortKey : 'title',
order : 1 order : -1
}, },
queryParams : { queryParams : {
@ -40,9 +40,9 @@ var Collection = PagableCollection.extend({
], ],
}, },
sortMappings : { // sortMappings : {
'series' : { sortKey : 'series.sortTitle' } // 'this' : { sortKey : 'this.sortTitle' }
}, // },
parseState : function(resp) { parseState : function(resp) {
return { totalRecords : resp.totalRecords }; return { totalRecords : resp.totalRecords };

@ -3,16 +3,15 @@ var Marionette = require('marionette');
var Backgrid = require('backgrid'); var Backgrid = require('backgrid');
var CutoffUnmetCollection = require('./CutoffUnmetCollection'); var CutoffUnmetCollection = require('./CutoffUnmetCollection');
var SelectAllCell = require('../../Cells/SelectAllCell'); var SelectAllCell = require('../../Cells/SelectAllCell');
var SeriesTitleCell = require('../../Cells/SeriesTitleCell'); var MovieTitleCell = require('../../Cells/MovieTitleCell');
var EpisodeNumberCell = require('../../Cells/EpisodeNumberCell'); var MovieStatusWithTextCell = require('../../Cells/MovieStatusWithTextCell');
var EpisodeTitleCell = require('../../Cells/EpisodeTitleCell');
var RelativeDateCell = require('../../Cells/RelativeDateCell'); var RelativeDateCell = require('../../Cells/RelativeDateCell');
var EpisodeStatusCell = require('../../Cells/EpisodeStatusCell');
var GridPager = require('../../Shared/Grid/Pager'); var GridPager = require('../../Shared/Grid/Pager');
var ToolbarLayout = require('../../Shared/Toolbar/ToolbarLayout'); var ToolbarLayout = require('../../Shared/Toolbar/ToolbarLayout');
var LoadingView = require('../../Shared/LoadingView'); var LoadingView = require('../../Shared/LoadingView');
var Messenger = require('../../Shared/Messenger'); var Messenger = require('../../Shared/Messenger');
var CommandController = require('../../Commands/CommandController'); var CommandController = require('../../Commands/CommandController');
require('backgrid.selectall'); require('backgrid.selectall');
require('../../Mixins/backbone.signalr.mixin'); require('../../Mixins/backbone.signalr.mixin');
@ -37,32 +36,25 @@ module.exports = Marionette.Layout.extend({
sortable : false sortable : false
}, },
{ {
name : 'series', name : 'this',
label : 'Series Title', label : 'Movie Title',
cell : SeriesTitleCell, cell : MovieTitleCell,
sortValue : 'series.sortTitle' sortValue : this.sortTitle
}, },
{ {
name : 'this', name : 'inCinemas',
label : 'Episode', label : 'In Cinemas',
cell : EpisodeNumberCell, cell : RelativeDateCell
sortable : false
}, },
{ {
name : 'this', name : 'physicalRelease',
label : 'Episode Title', label : 'Physical Release',
cell : EpisodeTitleCell, cell : RelativeDateCell
sortable : false
},
{
name : 'airDateUtc',
label : 'Air Date',
cell : RelativeDateCell
}, },
{ {
name : 'status', name : 'status',
label : 'Status', label : 'Status',
cell : EpisodeStatusCell, cell : MovieStatusWithTextCell,
sortable : false sortable : false
} }
], ],
@ -105,11 +97,6 @@ module.exports = Marionette.Layout.extend({
callback : this._searchSelected, callback : this._searchSelected,
ownerContext : this, ownerContext : this,
className : 'x-search-selected' className : 'x-search-selected'
},
{
title : 'Season Pass',
icon : 'icon-sonarr-monitored',
route : 'seasonpass'
} }
] ]
}; };
@ -148,9 +135,9 @@ module.exports = Marionette.Layout.extend({
})); }));
CommandController.bindToCommand({ CommandController.bindToCommand({
element : this.$('.x-search-selected'), element : this.$('.x-search-selected'),
command : { command : {
name : 'episodeSearch' name : 'moviesSearch'
} }
}); });
}, },
@ -172,7 +159,7 @@ module.exports = Marionette.Layout.extend({
if (selected.length === 0) { if (selected.length === 0) {
Messenger.show({ Messenger.show({
type : 'error', type : 'error',
message : 'No episodes selected' message : 'No movies selected'
}); });
return; return;
@ -180,9 +167,9 @@ module.exports = Marionette.Layout.extend({
var ids = _.pluck(selected, 'id'); var ids = _.pluck(selected, 'id');
CommandController.Execute('episodeSearch', { CommandController.Execute('moviesSearch', {
name : 'episodeSearch', name : 'moviesSearch',
episodeIds : ids movieIds : ids
}); });
} }
}); });

@ -49,7 +49,7 @@ module.exports = Marionette.Layout.extend({
}, },
{ {
name : 'physicalRelease', name : 'physicalRelease',
label : 'PhysicalRelease', label : 'Physical Release',
cell : RelativeDateCell cell : RelativeDateCell
}, },
{ {
@ -115,11 +115,6 @@ module.exports = Marionette.Layout.extend({
ownerContext : this, ownerContext : this,
className : 'x-unmonitor-selected' className : 'x-unmonitor-selected'
}, },
{
title : 'Season Pass',
icon : 'icon-sonarr-monitored',
route : 'seasonpass'
},
{ {
title : 'Rescan Drone Factory Folder', title : 'Rescan Drone Factory Folder',
icon : 'icon-sonarr-refresh', icon : 'icon-sonarr-refresh',

Loading…
Cancel
Save