Added missing view
This commit is contained in:
parent
9ff7aa1bf7
commit
05c7b4f4ef
|
@ -2,6 +2,7 @@
|
|||
using AutoMapper;
|
||||
using NzbDrone.Api.Calendar;
|
||||
using NzbDrone.Api.Episodes;
|
||||
using NzbDrone.Api.Missing;
|
||||
using NzbDrone.Api.QualityProfiles;
|
||||
using NzbDrone.Api.QualityType;
|
||||
using NzbDrone.Api.Resolvers;
|
||||
|
@ -52,6 +53,11 @@ namespace NzbDrone.Api
|
|||
|
||||
//Episode
|
||||
Mapper.CreateMap<Episode, EpisodeResource>();
|
||||
|
||||
//Missing
|
||||
Mapper.CreateMap<Episode, MissingResource>()
|
||||
.ForMember(dest => dest.SeriesTitle, opt => opt.MapFrom(src => src.Series.Title))
|
||||
.ForMember(dest => dest.EpisodeTitle, opt => opt.MapFrom(src => src.Title));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Nancy;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Api.Missing
|
||||
{
|
||||
public class MissingModule : NzbDroneApiModule
|
||||
{
|
||||
private readonly EpisodeService _episodeService;
|
||||
|
||||
public MissingModule(EpisodeService episodeService)
|
||||
: base("/missing")
|
||||
{
|
||||
_episodeService = episodeService;
|
||||
Get["/"] = x => GetMissingEpisodes();
|
||||
}
|
||||
|
||||
private Response GetMissingEpisodes()
|
||||
{
|
||||
bool includeSpecials;
|
||||
Boolean.TryParse(PrimitiveExtensions.ToNullSafeString(Request.Query.IncludeSpecials), out includeSpecials);
|
||||
|
||||
var episodes = _episodeService.EpisodesWithoutFiles(includeSpecials);
|
||||
return Mapper.Map<List<Episode>, List<MissingResource>>(episodes).AsResponse();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Api.Missing
|
||||
{
|
||||
public class MissingResource
|
||||
{
|
||||
public Int32 SeriesId { get; set; }
|
||||
public String SeriesTitle { get; set; }
|
||||
public Int32 EpisodeId { get; set; }
|
||||
public String EpisodeTitle { get; set; }
|
||||
public Int32 SeasonNumber { get; set; }
|
||||
public Int32 EpisodeNumber { get; set; }
|
||||
public DateTime? AirDate { get; set; }
|
||||
public String Overview { get; set; }
|
||||
}
|
||||
}
|
|
@ -120,6 +120,8 @@
|
|||
<Compile Include="FrontendModule\IndexModule.cs" />
|
||||
<Compile Include="FrontendModule\BootstrapModule.cs" />
|
||||
<Compile Include="FrontendModule\LessService.cs" />
|
||||
<Compile Include="Missing\MissingResource.cs" />
|
||||
<Compile Include="Missing\MissingModule.cs" />
|
||||
<Compile Include="Resolvers\EndTimeResolver.cs" />
|
||||
<Compile Include="Resolvers\NextAiringResolver.cs" />
|
||||
<Compile Include="Resolvers\NullableDatetimeToString.cs" />
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
'Calendar/CalendarCollectionView', 'Shared/NotificationView',
|
||||
'Shared/NotFoundView', 'MainMenuView', 'HeaderView',
|
||||
'Series/Details/SeriesDetailsView', 'Series/EpisodeCollection',
|
||||
'Settings/SettingsLayout'],
|
||||
'Settings/SettingsLayout', 'Missing/MissingCollectionView'],
|
||||
function (app, modalRegion) {
|
||||
|
||||
var controller = Backbone.Marionette.Controller.extend({
|
||||
|
@ -48,12 +48,23 @@
|
|||
|
||||
var settingsModel = new NzbDrone.Settings.SettingsModel();
|
||||
settingsModel.fetch({
|
||||
success: function(settings){
|
||||
success: function(settings) {
|
||||
NzbDrone.mainRegion.show(new NzbDrone.Settings.SettingsLayout(this, action, query, settings));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
missing: function(action, query) {
|
||||
this.setTitle('Missing');
|
||||
|
||||
var missingCollection = new NzbDrone.Missing.MissingCollection();
|
||||
missingCollection.fetch({
|
||||
success: function(missing) {
|
||||
NzbDrone.mainRegion.show(new NzbDrone.Missing.MissingCollectionView(this, action, query, missing));
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
notFound: function () {
|
||||
this.setTitle('Not Found');
|
||||
NzbDrone.mainRegion.show(new NzbDrone.Shared.NotFoundView(this));
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
define(['app', 'Missing/MissingModel'], function () {
|
||||
NzbDrone.Missing.MissingCollection = Backbone.Collection.extend({
|
||||
url: NzbDrone.Constants.ApiRoot + '/missing',
|
||||
model: NzbDrone.Missing.MissingModel,
|
||||
comparator: function(model) {
|
||||
return model.get('airDate');
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
<table class="table table-hover x-missing-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Series Title</th>
|
||||
<th>Episode</th>
|
||||
<th>Episode Title</th>
|
||||
<th>Air Date</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
|
@ -0,0 +1,75 @@
|
|||
'use strict';
|
||||
|
||||
define(['app', 'Missing/MissingItemView'], function (app) {
|
||||
NzbDrone.Missing.MissingCollectionView = Backbone.Marionette.CompositeView.extend({
|
||||
itemView: NzbDrone.Missing.MissingItemView,
|
||||
itemViewContainer: 'tbody',
|
||||
template: 'Missing/MissingCollectionTemplate',
|
||||
|
||||
ui:{
|
||||
table : '.x-missing-table'
|
||||
},
|
||||
|
||||
initialize: function (context, action, query, collection) {
|
||||
this.collection = collection;
|
||||
},
|
||||
onCompositeCollectionRendered: function() {
|
||||
this.ui.table.trigger('update');
|
||||
|
||||
if(!this.tableSorter && this.collection.length > 0)
|
||||
{
|
||||
this.tableSorter = this.ui.table.tablesorter({
|
||||
textExtraction: function (node) {
|
||||
return node.innerHTML;
|
||||
},
|
||||
sortList: [[3,1]],
|
||||
headers: {
|
||||
0: {
|
||||
sorter: 'innerHtml'
|
||||
},
|
||||
1: {
|
||||
sorter: false
|
||||
},
|
||||
2: {
|
||||
sorter: false
|
||||
},
|
||||
3: {
|
||||
sorter: 'date'
|
||||
},
|
||||
4: {
|
||||
sorter: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//Todo: We should extract these common settings out
|
||||
this.ui.table.find('th.header').each(function(){
|
||||
$(this).append('<i class="icon-sort pull-right">');
|
||||
});
|
||||
|
||||
this.ui.table.bind("sortEnd", function() {
|
||||
$(this).find('th.header i').each(function(){
|
||||
$(this).remove();
|
||||
});
|
||||
|
||||
$(this).find('th.header').each(function () {
|
||||
if (!$(this).hasClass('headerSortDown') && !$(this).hasClass('headerSortUp'))
|
||||
$(this).append('<i class="icon-sort pull-right">');
|
||||
});
|
||||
|
||||
$(this).find('th.headerSortDown').each(function(){
|
||||
$(this).append('<i class="icon-sort-up pull-right">');
|
||||
});
|
||||
|
||||
$(this).find('th.headerSortUp').each(function(){
|
||||
$(this).append('<i class="icon-sort-down pull-right">');
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ui.table.trigger('update');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
<td><a href="/series/details/{{seriesId}}">{{seriesTitle}}</a></td>
|
||||
<td>{{seasonNumber}}x{{paddedEpisodeNumber}}</td>
|
||||
<td name="episodeTitle"></td>
|
||||
<td><span title="{{formatedDateString}}" data-date="{{airDate}}">{{bestDateString}}</span></td>
|
||||
<td><i class="icon-search x-search" title="Search for Episode"></i></td>
|
|
@ -0,0 +1,16 @@
|
|||
'use strict';
|
||||
|
||||
define([
|
||||
'app',
|
||||
'Missing/MissingCollection'
|
||||
|
||||
], function () {
|
||||
NzbDrone.Missing.MissingItemView = Backbone.Marionette.ItemView.extend({
|
||||
template: 'Missing/MissingItemTemplate',
|
||||
tagName: 'tr',
|
||||
|
||||
onRender: function () {
|
||||
NzbDrone.ModelBinder.bind(this.model, this.el);
|
||||
}
|
||||
})
|
||||
})
|
|
@ -0,0 +1,12 @@
|
|||
define(['app'], function (app) {
|
||||
NzbDrone.Missing.MissingModel = Backbone.Model.extend({
|
||||
mutators: {
|
||||
bestDateString: function () {
|
||||
return bestDateString(this.get('airDate'));
|
||||
},
|
||||
paddedEpisodeNumber: function(){
|
||||
return this.get('episodeNumber');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
|
@ -6,7 +6,7 @@ function bestDateString(sourceDate){
|
|||
if (date.isYesterday()) return 'Yesterday';
|
||||
if (date.isToday()) return 'Today';
|
||||
if (date.isTomorrow()) return 'Tomorrow';
|
||||
if (date.isBefore(Date.create().addDays(7))) return date.format('{Weekday}');
|
||||
if (date.isAfter(Date.create('tomorrow')) && date.isBefore(Date.create().addDays(7))) return date.format('{Weekday}');
|
||||
|
||||
return date.format('{MM}/{dd}/{yyyy}');
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
'calendar': 'calendar',
|
||||
'settings': 'settings',
|
||||
'settings/:action(/:query)': 'settings',
|
||||
'missing': 'missing',
|
||||
':whatever': 'notFound'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -57,6 +57,7 @@ define(['app', 'Quality/QualityProfileCollection', 'Series/Index/SeriesItemView'
|
|||
}
|
||||
});
|
||||
|
||||
//Todo: We should extract these common settings out
|
||||
this.ui.table.find('th.header').each(function(){
|
||||
$(this).append('<i class="icon-sort pull-right">');
|
||||
});
|
||||
|
@ -72,11 +73,11 @@ define(['app', 'Quality/QualityProfileCollection', 'Series/Index/SeriesItemView'
|
|||
});
|
||||
|
||||
$(this).find('th.headerSortDown').each(function(){
|
||||
$(this).append('<i class="icon-sort-down pull-right">');
|
||||
$(this).append('<i class="icon-sort-up pull-right">');
|
||||
});
|
||||
|
||||
$(this).find('th.headerSortUp').each(function(){
|
||||
$(this).append('<i class="icon-sort-up pull-right">');
|
||||
$(this).append('<i class="icon-sort-down pull-right">');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ define('app', function () {
|
|||
window.NzbDrone.Settings.Notifications = {};
|
||||
window.NzbDrone.Settings.System = {};
|
||||
window.NzbDrone.Settings.Misc = {};
|
||||
window.NzbDrone.Missing = {};
|
||||
|
||||
window.NzbDrone.Events = {
|
||||
OpenModalDialog :'openModal',
|
||||
|
|
Binary file not shown.
|
@ -61,7 +61,7 @@ namespace NzbDrone.Core.Tvdb
|
|||
[XmlElement]
|
||||
public int EpisodeNumber { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
[XmlElement]
|
||||
public DateTime FirstAired { get; set; }
|
||||
|
||||
[XmlElement]
|
||||
|
|
Loading…
Reference in New Issue