Series Details started

pull/6/head
Mark McDowall 12 years ago
parent e1a3637107
commit bb27995eaf

@ -1,6 +1,7 @@
using System;
using AutoMapper;
using NzbDrone.Api.Calendar;
using NzbDrone.Api.Episodes;
using NzbDrone.Api.QualityProfiles;
using NzbDrone.Api.QualityType;
using NzbDrone.Api.Resolvers;
@ -48,6 +49,9 @@ namespace NzbDrone.Api
.ForMember(dest => dest.EpisodeTitle, opt => opt.MapFrom(src => src.Title))
.ForMember(dest => dest.Start, opt => opt.MapFrom(src => src.AirDate))
.ForMember(dest => dest.End, opt => opt.ResolveUsing<EndTimeResolver>());
//Episode
Mapper.CreateMap<Episode, EpisodeResource>();
}
}
}

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using AutoMapper;
using Nancy;
using NzbDrone.Api.Extensions;
using NzbDrone.Core.Tv;
namespace NzbDrone.Api.Episodes
{
public class EpisodeModule : NzbDroneApiModule
{
private readonly EpisodeService _episodeService;
public EpisodeModule(EpisodeService episodeService)
: base("/episodes")
{
_episodeService = episodeService;
Get["/{seriesId}"] = x => GetEpisodesForSeries(x.SeriesId);
}
private Response GetEpisodesForSeries(int seriesId)
{
var episodes = _episodeService.GetEpisodeBySeries(seriesId);
return Mapper.Map<List<Episode>, List<EpisodeResource>>(episodes).AsResponse();
}
}
}

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NzbDrone.Core.Tv;
namespace NzbDrone.Api.Episodes
{
public class EpisodeResource
{
public Int32 SeriesId { get; set; }
public Int32 EpisodeId { get; set; }
public Int32 EpisodeFileId { get; set; }
public Int32 SeasonNumber { get; set; }
public Int32 EpisodeNumber { get; set; }
public String Title { get; set; }
public DateTime AirDate { get; set; }
public Int32 Status { get; set; }
public String Overview { get; set; }
public EpisodeFile EpisodeFile { get; set; }
}
}

@ -113,6 +113,8 @@
<Compile Include="Calendar\CalendarModule.cs" />
<Compile Include="Calendar\CalendarResource.cs" />
<Compile Include="Directories\DirectoryModule.cs" />
<Compile Include="Episodes\EpisodeModule.cs" />
<Compile Include="Episodes\EpisodeResource.cs" />
<Compile Include="Extensions\NancyJsonSerializer.cs" />
<Compile Include="Extensions\Serializer.cs" />
<Compile Include="FrontendModule\IndexModule.cs" />

@ -1,6 +1,9 @@
define(['app', 'Shared/ModalRegion', 'AddSeries/AddSeriesLayout', 'Series/SeriesCollectionView',
'Upcoming/UpcomingCollectionView', 'Calendar/CalendarCollectionView', 'Shared/NotificationView',
'Shared/NotFoundView', 'MainMenuView', 'HeaderView'], function (app, modalRegion) {
define(['app', 'Shared/ModalRegion', 'AddSeries/AddSeriesLayout',
'Series/SeriesCollectionView', 'Upcoming/UpcomingCollectionView',
'Calendar/CalendarCollectionView', 'Shared/NotificationView',
'Shared/NotFoundView', 'MainMenuView', 'HeaderView',
'Series/Details/SeriesDetailsView', 'Series/Details/EpisodeCollection'],
function (app, modalRegion) {
var controller = Backbone.Marionette.Controller.extend({
@ -26,6 +29,36 @@
NzbDrone.mainRegion.show(new NzbDrone.Calendar.CalendarCollectionView(this, action, query, calendarCollection));
},
seriesDetails: function (query) {
this.setTitle('Series Title Goes Here');
// var seriesModel = new NzbDrone.Series.SeriesModel();
// seriesModel.fetch();
var seriesEpisodes = new NzbDrone.Series.Details.EpisodeCollection({ seriesId: query });
seriesEpisodes.fetch({
success: function (collection) {
var seasons = collection.models.groupBy(function(episode){
var seasonNumber = episode.get('seasonNumber');
if (seasonNumber === undefined)
return 0;
return seasonNumber;
});
var seasonCollection = new NzbDrone.Series.Details.SeasonCollection();
$.each(seasons, function(index, season){
seasonCollection.add(new NzbDrone.Series.Details.SeasonModel(
{ seasonNumber: index, episodes: season })
);
});
NzbDrone.mainRegion.show(new NzbDrone.Series.Details.SeriesDetailsView({ collection: seasonCollection }));
}
});
},
notFound: function () {
this.setTitle('Not Found');
NzbDrone.mainRegion.show(new NzbDrone.Shared.NotFoundView(this));

@ -32,6 +32,7 @@
<CodeAnalysisIgnoreGeneratedCode>true</CodeAnalysisIgnoreGeneratedCode>
</PropertyGroup>
<ItemGroup>
<Content Include="HeaderView.js" />
<Content Include="MainMenuView.js" />
<Content Include="AddSeries\addSeries.css" />
<Content Include="AddSeries\AddSeriesLayout.js" />
@ -121,6 +122,12 @@
<Content Include="Routing.js" />
<Content Include="Series\Delete\DeleteSeriesTemplate.html" />
<Content Include="Series\Delete\DeleteSeriesView.js" />
<Content Include="Series\Details\EpisodeModel.js" />
<Content Include="Series\Details\SeasonCollection.js" />
<Content Include="Series\Details\SeasonCollectionTemplate.html" />
<Content Include="Series\Details\SeasonCollectionView.js" />
<Content Include="Series\Details\SeriesDetailsTemplate.html" />
<Content Include="Series\Details\SeriesDetailsView.js" />
<Content Include="Series\Edit\EditSeriesTemplate.html" />
<Content Include="Series\Edit\EditSeriesView.js" />
<Content Include="Series\EmptySeriesCollectionTemplate.html" />

@ -9,6 +9,7 @@
'series/index': 'series',
'series/add': 'addSeries',
'series/add/:action(/:query)': 'addSeries',
'series/details/:query': 'seriesDetails',
'upcoming': 'upcoming',
'upcoming/index': 'upcoming',
'calendar': 'calendar',

@ -0,0 +1,13 @@
define(['app', 'Series/Details/EpisodeModel'], function () {
NzbDrone.Series.Details.EpisodeCollection = Backbone.Collection.extend({
initialize: function(options) {
this.seriesId = options.seriesId;
},
url: function(){
return NzbDrone.Constants.ApiRoot + '/episodes/' + this.seriesId;
},
model: NzbDrone.Series.Details.EpisodeModel
});
});

@ -0,0 +1,24 @@
'use strict';
define([
'app',
'Series/Details/SeasonModel'
], function () {
NzbDrone.Series.Details.EpisodeItemView = Backbone.Marionette.ItemView.extend({
template: 'Series/Details/EpisodeItemTemplate',
tagName: 'tr',
ui: {
},
events: {
},
onRender: function () {
NzbDrone.ModelBinder.bind(this.model, this.el);
}
});
});

@ -0,0 +1,12 @@
define(['app'], function (app) {
NzbDrone.Series.Details.EpisodeModel = Backbone.Model.extend({
mutators: {
},
defaults: {
seasonNumber: 0
}
});
});

@ -0,0 +1,10 @@
define(['app'], function (app) {
NzbDrone.Series.Details.SeasonCollection = Backbone.Collection.extend({
// Todo: Why does this throw: "this.model is undefined" - Chnaging to another model fixes it
//model: NzbDrone.Series.Details.SeasonModel,
model: NzbDrone.Series.Details.EpisodeModel,
comparator: function(model) {
return -model.get('seasonNumber');
}
});
});

@ -0,0 +1,13 @@
<h3>Season {{seasonNumber}}</h3>
<table class="table table-hover x-season-table">
<thead>
<tr>
<th>#</th>
<th>Title</th>
<th>Air Date</th>
<th>Quality</th>
<th>Controls</th>
</tr>
</thead>
<tbody></tbody>
</table>

@ -0,0 +1,15 @@
'use strict';
define(['app', 'Series/Details/EpisodeItemView'], function (app) {
NzbDrone.Series.Details.SeasonCollectionView = Backbone.Marionette.CompositeView.extend({
itemView: NzbDrone.Series.Details.EpisodeItemView,
itemViewContainer: '#seasons',
template: 'Series/Details/SeasonCollectionTemplate',
initialize: function() {
var episodes = this.model.get('episodes');
var test = 1;
//this.collection
}
});
});

@ -0,0 +1,11 @@
define(['app', 'Series/Details/SeasonCollection'], function (app) {
NzbDrone.Series.Details.SeasonModel = Backbone.Model.extend({
//Season Number
//Episodes
initialize: function(options) {
this.seasonNumber = options.seasonNumber;
this.episodes = options.episodes;
}
});
});

@ -0,0 +1,4 @@
<div>
<div id="details"></div>
<div id="seasons"></div>
</div>

@ -0,0 +1,19 @@
define(['app', 'Quality/QualityProfileCollection', 'Series/Details/SeasonCollectionView'], function (app, qualityProfileCollection) {
NzbDrone.Series.Details.SeriesDetailsView = Backbone.Marionette.CompositeView.extend({
itemView: NzbDrone.Series.Details.SeasonCollectionView,
itemViewContainer: '#seasons',
template: 'Series/Details/SeriesDetailsTemplate',
qualityProfileCollection: qualityProfileCollection,
initialize: function (options) {
this.collection = options.collection;
this.qualityProfileCollection.fetch();
},
onCompositeCollectionRendered: function()
{
var test = 1;
}
});
});

@ -32,6 +32,7 @@ define('app', function () {
window.NzbDrone.Series = {};
window.NzbDrone.Series.Edit = {};
window.NzbDrone.Series.Delete = {};
window.NzbDrone.Series.Details = {};
window.NzbDrone.AddSeries = {};
window.NzbDrone.AddSeries.New = {};
window.NzbDrone.AddSeries.Existing = {};

@ -17,7 +17,7 @@ namespace NzbDrone.Core.Tv
Episode GetEpisode(int id);
Episode GetEpisode(int seriesId, int seasonNumber, int episodeNumber);
Episode GetEpisode(int seriesId, DateTime date);
IList<Episode> GetEpisodeBySeries(int seriesId);
List<Episode> GetEpisodeBySeries(int seriesId);
IList<Episode> GetEpisodesBySeason(int seriesId, int seasonNumber);
IList<Episode> GetEpisodesByParseResult(EpisodeParseResult parseResult);
IList<Episode> EpisodesWithoutFiles(bool includeSpecials);
@ -56,32 +56,32 @@ namespace NzbDrone.Core.Tv
_episodeRepository.Insert(episode);
}
public virtual Episode GetEpisode(int id)
public Episode GetEpisode(int id)
{
return _episodeRepository.Get(id);
}
public virtual Episode GetEpisode(int seriesId, int seasonNumber, int episodeNumber)
public Episode GetEpisode(int seriesId, int seasonNumber, int episodeNumber)
{
return _episodeRepository.Get(seriesId, seasonNumber, episodeNumber);
}
public virtual Episode GetEpisode(int seriesId, DateTime date)
public Episode GetEpisode(int seriesId, DateTime date)
{
return _episodeRepository.Get(seriesId, date);
}
public virtual IList<Episode> GetEpisodeBySeries(int seriesId)
public List<Episode> GetEpisodeBySeries(int seriesId)
{
return _episodeRepository.GetEpisodes(seriesId);
return _episodeRepository.GetEpisodes(seriesId).ToList();
}
public virtual IList<Episode> GetEpisodesBySeason(int seriesId, int seasonNumber)
public IList<Episode> GetEpisodesBySeason(int seriesId, int seasonNumber)
{
return _episodeRepository.GetEpisodes(seriesId, seasonNumber);
}
public virtual IList<Episode> GetEpisodesByParseResult(EpisodeParseResult parseResult)
public IList<Episode> GetEpisodesByParseResult(EpisodeParseResult parseResult)
{
var result = new List<Episode>();
@ -159,22 +159,22 @@ namespace NzbDrone.Core.Tv
return result;
}
public virtual IList<Episode> EpisodesWithoutFiles(bool includeSpecials)
public IList<Episode> EpisodesWithoutFiles(bool includeSpecials)
{
return _episodeRepository.EpisodesWithoutFiles(includeSpecials);
}
public virtual IList<Episode> GetEpisodesByFileId(int episodeFileId)
public IList<Episode> GetEpisodesByFileId(int episodeFileId)
{
return _episodeRepository.GetEpisodeByFileId(episodeFileId);
}
public virtual IList<Episode> EpisodesWithFiles()
public IList<Episode> EpisodesWithFiles()
{
return _episodeRepository.EpisodesWithFiles();
}
public virtual void RefreshEpisodeInfo(Series series)
public void RefreshEpisodeInfo(Series series)
{
logger.Trace("Starting episode info refresh for series: {0}", series.Title.WithDefault(series.Id));
var successCount = 0;
@ -270,17 +270,17 @@ namespace NzbDrone.Core.Tv
DeleteEpisodesNotInTvdb(series, tvdbEpisodes);
}
public virtual void UpdateEpisode(Episode episode)
public void UpdateEpisode(Episode episode)
{
_episodeRepository.Update(episode);
}
public virtual IList<int> GetEpisodeNumbersBySeason(int seriesId, int seasonNumber)
public IList<int> GetEpisodeNumbersBySeason(int seriesId, int seasonNumber)
{
return GetEpisodesBySeason(seriesId, seasonNumber).Select(c => c.Id).ToList();
}
public virtual void SetEpisodeIgnore(int episodeId, bool isIgnored)
public void SetEpisodeIgnore(int episodeId, bool isIgnored)
{
var episode = _episodeRepository.Get(episodeId);
_episodeRepository.SetIgnoreFlat(episode, isIgnored);
@ -288,7 +288,7 @@ namespace NzbDrone.Core.Tv
logger.Info("Ignore flag for Episode:{0} was set to {1}", episodeId, isIgnored);
}
public virtual bool IsFirstOrLastEpisodeOfSeason(int seriesId, int seasonNumber, int episodeNumber)
public bool IsFirstOrLastEpisodeOfSeason(int seriesId, int seasonNumber, int episodeNumber)
{
var episodes = GetEpisodesBySeason(seriesId, seasonNumber).OrderBy(e => e.EpisodeNumber);
@ -316,7 +316,7 @@ namespace NzbDrone.Core.Tv
logger.Trace("Deleted episodes that no longer exist in TVDB for {0}", series.Id);
}
public virtual void SetPostDownloadStatus(List<int> episodeIds, PostDownloadStatusType postDownloadStatus)
public void SetPostDownloadStatus(List<int> episodeIds, PostDownloadStatusType postDownloadStatus)
{
if (episodeIds.Count == 0) throw new ArgumentException("episodeIds should contain one or more episode ids.");
@ -332,12 +332,12 @@ namespace NzbDrone.Core.Tv
logger.Trace("Updating PostDownloadStatus for {0} episode(s) to {1}", episodeIds.Count, postDownloadStatus);
}
public virtual void UpdateEpisodes(List<Episode> episodes)
public void UpdateEpisodes(List<Episode> episodes)
{
_episodeRepository.UpdateMany(episodes);
}
public virtual Episode GetEpisodeBySceneNumbering(int seriesId, int seasonNumber, int episodeNumber)
public Episode GetEpisodeBySceneNumbering(int seriesId, int seasonNumber, int episodeNumber)
{
return _episodeRepository.GetEpisodeBySceneNumbering(seriesId, seasonNumber, episodeNumber);
}

@ -53,7 +53,5 @@ namespace NzbDrone.Core.Tv
public int EpisodeFileCount { get; set; }
public int SeasonCount { get; set; }
public DateTime? NextAiring { get; set; }
public List<Episode> Episodes { get; set; }
}
}
Loading…
Cancel
Save