mirror of https://github.com/Radarr/Radarr
basic implementation of the wanted tab (#31)
* top buttons don't yet work * new missing module for movies * find missing movies method to movie service * new movie status cell with text * adapted UI missing collection and layout
This commit is contained in:
parent
10dc3993df
commit
da2d075aa8
|
@ -118,6 +118,7 @@
|
||||||
<Compile Include="Indexers\ReleasePushModule.cs" />
|
<Compile Include="Indexers\ReleasePushModule.cs" />
|
||||||
<Compile Include="Movies\MovieFileModule.cs" />
|
<Compile Include="Movies\MovieFileModule.cs" />
|
||||||
<Compile Include="Movies\MovieModule.cs" />
|
<Compile Include="Movies\MovieModule.cs" />
|
||||||
|
<Compile Include="Movies\MovieModuleWithSignalR.cs" />
|
||||||
<Compile Include="Movies\RenameMovieModule.cs" />
|
<Compile Include="Movies\RenameMovieModule.cs" />
|
||||||
<Compile Include="Movies\RenameMovieResource.cs" />
|
<Compile Include="Movies\RenameMovieResource.cs" />
|
||||||
<Compile Include="Movies\MovieEditorModule.cs" />
|
<Compile Include="Movies\MovieEditorModule.cs" />
|
||||||
|
@ -260,6 +261,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\MovieMissingModule.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="app.config" />
|
<None Include="app.config" />
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace NzbDrone.Api.Wanted
|
||||||
ISeriesService seriesService,
|
ISeriesService seriesService,
|
||||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||||
IBroadcastSignalRMessage signalRBroadcaster)
|
IBroadcastSignalRMessage signalRBroadcaster)
|
||||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/missing")
|
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/missing_episodes")
|
||||||
{
|
{
|
||||||
GetResourcePaged = GetMissingEpisodes;
|
GetResourcePaged = GetMissingEpisodes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
using NzbDrone.Api.Movie;
|
||||||
|
using NzbDrone.Api.Movies;
|
||||||
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.SignalR;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Core.Datastore.Events;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Wanted
|
||||||
|
{
|
||||||
|
class MovieMissingModule : NzbDroneRestModuleWithSignalR<MovieResource, Core.Tv.Movie>,
|
||||||
|
IHandle<MovieGrabbedEvent>,
|
||||||
|
IHandle<MovieDownloadedEvent>
|
||||||
|
{
|
||||||
|
protected readonly IMovieService _movieService;
|
||||||
|
|
||||||
|
public MovieMissingModule(IMovieService movieService,
|
||||||
|
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||||
|
IBroadcastSignalRMessage signalRBroadcaster)
|
||||||
|
: base(signalRBroadcaster, "wanted/missing")
|
||||||
|
{
|
||||||
|
|
||||||
|
_movieService = movieService;
|
||||||
|
GetResourcePaged = GetMissingMovies;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PagingResource<MovieResource> GetMissingMovies(PagingResource<MovieResource> pagingResource)
|
||||||
|
{
|
||||||
|
var pagingSpec = pagingResource.MapToPagingSpec<MovieResource, Core.Tv.Movie>("physicalRelease", SortDirection.Descending);
|
||||||
|
|
||||||
|
if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false")
|
||||||
|
{
|
||||||
|
pagingSpec.FilterExpression = v => v.Monitored == false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pagingSpec.FilterExpression = v => v.Monitored == true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resource = ApplyToPage(_movieService.MoviesWithoutFiles, pagingSpec, v => MapToResource(v, false));
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
var resource = movie.ToResource();
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(MovieGrabbedEvent message)
|
||||||
|
{
|
||||||
|
var resource = message.Movie.Movie.ToResource();
|
||||||
|
|
||||||
|
//add a grabbed field in MovieResource?
|
||||||
|
//resource.Grabbed = true;
|
||||||
|
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(MovieDownloadedEvent message)
|
||||||
|
{
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, message.Movie.Movie.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Datastore.Extensions;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Tv
|
namespace NzbDrone.Core.Tv
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,7 @@ namespace NzbDrone.Core.Tv
|
||||||
Movie FindByImdbId(string imdbid);
|
Movie FindByImdbId(string imdbid);
|
||||||
Movie FindByTitleSlug(string slug);
|
Movie FindByTitleSlug(string slug);
|
||||||
List<Movie> MoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored);
|
List<Movie> MoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored);
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -132,5 +133,21 @@ namespace NzbDrone.Core.Tv
|
||||||
|
|
||||||
return query.ToList();
|
return query.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec)
|
||||||
|
{
|
||||||
|
|
||||||
|
var query = Query.Where(pagingSpec.FilterExpression)
|
||||||
|
.AndWhere(m => m.MovieFileId == 0)
|
||||||
|
.AndWhere(m => m.Status == MovieStatusType.Released)
|
||||||
|
.OrderBy(pagingSpec.OrderByClause(), pagingSpec.ToSortDirection())
|
||||||
|
.Skip(pagingSpec.PagingOffset())
|
||||||
|
.Take(pagingSpec.PageSize);
|
||||||
|
|
||||||
|
pagingSpec.Records = query.ToList();
|
||||||
|
pagingSpec.TotalRecords = pagingSpec.Records.Count;
|
||||||
|
|
||||||
|
return pagingSpec;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,6 +12,7 @@ using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Tv.Events;
|
using NzbDrone.Core.Tv.Events;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Tv
|
namespace NzbDrone.Core.Tv
|
||||||
{
|
{
|
||||||
|
@ -27,6 +28,7 @@ namespace NzbDrone.Core.Tv
|
||||||
Movie FindByTitleSlug(string slug);
|
Movie FindByTitleSlug(string slug);
|
||||||
Movie GetMovieByFileId(int fileId);
|
Movie GetMovieByFileId(int fileId);
|
||||||
List<Movie> GetMoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored);
|
List<Movie> GetMoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored);
|
||||||
|
PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec);
|
||||||
void DeleteMovie(int movieId, bool deleteFiles);
|
void DeleteMovie(int movieId, bool deleteFiles);
|
||||||
List<Movie> GetAllMovies();
|
List<Movie> GetAllMovies();
|
||||||
Movie UpdateMovie(Movie movie);
|
Movie UpdateMovie(Movie movie);
|
||||||
|
@ -232,5 +234,12 @@ namespace NzbDrone.Core.Tv
|
||||||
|
|
||||||
return episodes;
|
return episodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec)
|
||||||
|
{
|
||||||
|
var movieResult = _movieRepository.MoviesWithoutFiles(pagingSpec);
|
||||||
|
|
||||||
|
return movieResult;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
var NzbDroneCell = require('./NzbDroneCell');
|
||||||
|
|
||||||
|
//used in Wanted tab
|
||||||
|
module.exports = NzbDroneCell.extend({
|
||||||
|
className : 'movie-status-text-cell',
|
||||||
|
|
||||||
|
render : function() {
|
||||||
|
this.$el.empty();
|
||||||
|
var monitored = this.model.get('monitored');
|
||||||
|
var status = this.model.get('status');
|
||||||
|
var inCinemas = this.model.get("inCinemas");
|
||||||
|
var date = new Date(inCinemas);
|
||||||
|
var timeSince = new Date().getTime() - date.getTime();
|
||||||
|
var numOfMonths = timeSince / 1000 / 60 / 60 / 24 / 30;
|
||||||
|
|
||||||
|
if (status === 'released') {
|
||||||
|
this.$el.html('<div class="released-banner"><i class="icon-sonarr-movie-released grid-icon" title=""></i> Released</div>');
|
||||||
|
this._setStatusWeight(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numOfMonths > 3) {
|
||||||
|
this.$el.html('<div class="released-banner"><i class="icon-sonarr-movie-released grid-icon" title=""></i> Released</div>');//TODO: Update for PreDB.me
|
||||||
|
this._setStatusWeight(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numOfMonths < 3) {
|
||||||
|
this.$el.html('<div class="cinemas-banner"><i class="icon-sonarr-movie-cinemas grid-icon" title=""></i> In Cinemas</div>');
|
||||||
|
this._setStatusWeight(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status === "announced") {
|
||||||
|
this.$el.html('<div class="announced-banner"><i class="icon-sonarr-movie-announced grid-icon" title=""></i> Announced</div>');
|
||||||
|
this._setStatusWeight(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
_setStatusWeight : function(weight) {
|
||||||
|
this.model.set('statusWeight', weight, { silent : true });
|
||||||
|
}
|
||||||
|
});
|
|
@ -55,6 +55,10 @@
|
||||||
width : 150px;
|
width : 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.movie-status-text-cell {
|
||||||
|
width : 150px;
|
||||||
|
}
|
||||||
|
|
||||||
.history-event-type-cell {
|
.history-event-type-cell {
|
||||||
width : 10px;
|
width : 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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/missing',
|
url : window.NzbDrone.ApiRoot + '/wanted/missing',
|
||||||
model : EpisodeModel,
|
model : MovieModel,
|
||||||
tableName : 'wanted.missing',
|
tableName : 'wanted.missing',
|
||||||
|
|
||||||
state : {
|
state : {
|
||||||
pageSize : 15,
|
pageSize : 15,
|
||||||
sortKey : 'airDateUtc',
|
sortKey : 'inCinemas',
|
||||||
order : 1
|
order : -1
|
||||||
},
|
},
|
||||||
|
|
||||||
queryParams : {
|
queryParams : {
|
||||||
|
@ -39,10 +39,6 @@ var Collection = PagableCollection.extend({
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
sortMappings : {
|
|
||||||
'series' : { sortKey : 'series.sortTitle' }
|
|
||||||
},
|
|
||||||
|
|
||||||
parseState : function(resp) {
|
parseState : function(resp) {
|
||||||
return { totalRecords : resp.totalRecords };
|
return { totalRecords : resp.totalRecords };
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,11 +5,9 @@ var Marionette = require('marionette');
|
||||||
var Backgrid = require('backgrid');
|
var Backgrid = require('backgrid');
|
||||||
var MissingCollection = require('./MissingCollection');
|
var MissingCollection = require('./MissingCollection');
|
||||||
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 EpisodeTitleCell = require('../../Cells/EpisodeTitleCell');
|
|
||||||
var RelativeDateCell = require('../../Cells/RelativeDateCell');
|
var RelativeDateCell = require('../../Cells/RelativeDateCell');
|
||||||
var EpisodeStatusCell = require('../../Cells/EpisodeStatusCell');
|
var MovieStatusWithTextCell = require('../../Cells/MovieStatusWithTextCell');
|
||||||
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');
|
||||||
|
@ -39,35 +37,29 @@ module.exports = Marionette.Layout.extend({
|
||||||
headerCell : 'select-all',
|
headerCell : 'select-all',
|
||||||
sortable : false
|
sortable : false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name : 'series',
|
|
||||||
label : 'Series Title',
|
|
||||||
cell : SeriesTitleCell,
|
|
||||||
sortValue : 'series.sortTitle'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name : 'this',
|
name : 'this',
|
||||||
label : 'Episode',
|
label : 'Movie Title',
|
||||||
cell : EpisodeNumberCell,
|
cell : MovieTitleCell,
|
||||||
sortable : false
|
sortable : false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'this',
|
name : 'inCinemas',
|
||||||
label : 'Episode Title',
|
label : 'In Cinemas',
|
||||||
cell : EpisodeTitleCell,
|
cell : RelativeDateCell
|
||||||
sortable : false
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'airDateUtc',
|
name : 'physicalRelease',
|
||||||
label : 'Air Date',
|
label : 'PhysicalRelease',
|
||||||
cell : RelativeDateCell
|
cell : RelativeDateCell
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'status',
|
name : 'status',
|
||||||
label : 'Status',
|
label : 'Status',
|
||||||
cell : EpisodeStatusCell,
|
cell : MovieStatusWithTextCell,
|
||||||
sortable : false
|
sortable : false
|
||||||
}
|
},
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
initialize : function() {
|
initialize : function() {
|
||||||
|
|
Loading…
Reference in New Issue