From 81e155ae42b09325e68aac118be1c98ceabf196e Mon Sep 17 00:00:00 2001 From: Keivan Date: Mon, 4 Oct 2010 23:21:18 -0700 Subject: [PATCH] Added basic episode support --- NzbDrone.Core.Test/DbConfigControllerTest.cs | 4 +- NzbDrone.Core.Test/EpisodeProviderTest.cs | 15 +++ NzbDrone.Core.Test/Fixtures.cs | 2 +- NzbDrone.Core.Test/MockLib.cs | 19 ++-- NzbDrone.Core.Test/NzbDrone.Core.Test.csproj | 18 ++-- NzbDrone.Core.Test/SabControllerTest.cs | 10 +- .../{SeriesTest.cs => SeriesProviderTest.cs} | 59 +++++++----- NzbDrone.Core.Test/TvDbControllerTest.cs | 71 +++++++++++++- NzbDrone.Core/{Main.cs => CentralDispatch.cs} | 30 +++++- NzbDrone.Core/NzbDrone.Core.csproj | 10 +- NzbDrone.Core/Providers/ConfigProvider.cs | 21 ++--- NzbDrone.Core/Providers/EpisodeProvider.cs | 75 +++++++++++---- NzbDrone.Core/Providers/IEpisodeProvider.cs | 5 +- NzbDrone.Core/Providers/ISeasonProvider.cs | 7 +- NzbDrone.Core/Providers/ISeriesProvider.cs | 2 +- NzbDrone.Core/Providers/ITvDbProvider.cs | 2 +- NzbDrone.Core/Providers/SabProvider.cs | 14 +-- NzbDrone.Core/Providers/SeasonProvider.cs | 54 +++++++++++ NzbDrone.Core/Providers/SeriesProvider.cs | 29 +++--- NzbDrone.Core/Providers/TvDbProvider.cs | 14 ++- NzbDrone.Core/Repository/Config.cs | 1 + NzbDrone.Core/Repository/Episode.cs | 27 ------ NzbDrone.Core/Repository/Episode/Episode.cs | 16 ++++ .../Repository/Episode/EpisodeInfo.cs | 24 +++++ .../Repository/Episode/RemoteEpisode.cs | 17 ++++ NzbDrone.Core/Repository/LocalEpisode.cs | 11 --- NzbDrone.Core/Repository/RemoteEpisode.cs | 12 --- NzbDrone.Core/Repository/Season.cs | 6 +- NzbDrone.Core/Repository/Series.cs | 7 +- NzbDrone.Web/Controllers/SeriesController.cs | 93 +++---------------- NzbDrone.Web/Global.asax.cs | 4 +- NzbDrone.Web/Views/Series/Details.aspx | 65 ++++++++----- NzbDrone.Web/Views/Series/index.aspx | 4 +- 33 files changed, 458 insertions(+), 290 deletions(-) create mode 100644 NzbDrone.Core.Test/EpisodeProviderTest.cs rename NzbDrone.Core.Test/{SeriesTest.cs => SeriesProviderTest.cs} (67%) rename NzbDrone.Core/{Main.cs => CentralDispatch.cs} (69%) create mode 100644 NzbDrone.Core/Providers/SeasonProvider.cs delete mode 100644 NzbDrone.Core/Repository/Episode.cs create mode 100644 NzbDrone.Core/Repository/Episode/Episode.cs create mode 100644 NzbDrone.Core/Repository/Episode/EpisodeInfo.cs create mode 100644 NzbDrone.Core/Repository/Episode/RemoteEpisode.cs delete mode 100644 NzbDrone.Core/Repository/LocalEpisode.cs delete mode 100644 NzbDrone.Core/Repository/RemoteEpisode.cs diff --git a/NzbDrone.Core.Test/DbConfigControllerTest.cs b/NzbDrone.Core.Test/DbConfigControllerTest.cs index 55d3f992c..97d34264f 100644 --- a/NzbDrone.Core.Test/DbConfigControllerTest.cs +++ b/NzbDrone.Core.Test/DbConfigControllerTest.cs @@ -26,7 +26,7 @@ namespace NzbDrone.Core.Test var repo = new Mock(); var config = new Config { Key = key, Value = value }; repo.Setup(r => r.Single(key)).Returns(config); - var target = new ConfigProvider(new Mock().Object, repo.Object); + var target = new ConfigProvider(repo.Object); //Act target.SetValue(key, value); @@ -45,7 +45,7 @@ namespace NzbDrone.Core.Test //Arrange var repo = new Mock(); repo.Setup(r => r.Single(It.IsAny())).Returns(null).Verifiable(); - var target = new ConfigProvider(new Mock().Object, repo.Object); + var target = new ConfigProvider(repo.Object); //Act target.SetValue(key, value); diff --git a/NzbDrone.Core.Test/EpisodeProviderTest.cs b/NzbDrone.Core.Test/EpisodeProviderTest.cs new file mode 100644 index 000000000..91caa7b55 --- /dev/null +++ b/NzbDrone.Core.Test/EpisodeProviderTest.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Gallio.Framework; +using MbUnit.Framework; +using MbUnit.Framework.ContractVerifiers; + +namespace NzbDrone.Core.Test +{ + [TestFixture] + public class EpisodeProviderTest + { + + } +} diff --git a/NzbDrone.Core.Test/Fixtures.cs b/NzbDrone.Core.Test/Fixtures.cs index ec26a1b81..c72442d7c 100644 --- a/NzbDrone.Core.Test/Fixtures.cs +++ b/NzbDrone.Core.Test/Fixtures.cs @@ -27,7 +27,7 @@ namespace NzbDrone.Core.Test [SetUp] public void Setup() { - Main.ConfigureNlog(); + CentralDispatch.ConfigureNlog(); } } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/MockLib.cs b/NzbDrone.Core.Test/MockLib.cs index 439a335f5..2e7235079 100644 --- a/NzbDrone.Core.Test/MockLib.cs +++ b/NzbDrone.Core.Test/MockLib.cs @@ -7,6 +7,7 @@ using Moq; using NzbDrone.Core.Providers; using SubSonic.DataProviders; using SubSonic.Repository; +using TvdbLib; namespace NzbDrone.Core.Test { @@ -17,12 +18,9 @@ namespace NzbDrone.Core.Test { public static string[] StandardSeries { - get { return new string[] { "C:\\TV\\The Simpsons", "C:\\TV\\Family Guy" }; } + get { return new string[] { "c:\\tv\\the simpsons", "c:\\tv\\family guy", "c:\\tv\\southpark", "c:\\tv\\24" }; } } - - - public static IRepository GetEmptyRepository() { var provider = ProviderFactory.GetProvider("Data Source=" + Guid.NewGuid() + ".testdb;Version=3;New=True", "System.Data.SQLite"); @@ -39,15 +37,12 @@ namespace NzbDrone.Core.Test } } - public static IDiskProvider StandardDisk + public static IDiskProvider GetStandardDisk() { - get - { - var mock = new Mock(); - mock.Setup(c => c.GetDirectories(It.IsAny())).Returns(StandardSeries); - mock.Setup(c => c.Exists(It.Is(d => StandardSeries.Contains(d)))).Returns(true); - return mock.Object; - } + var mock = new Mock(); + mock.Setup(c => c.GetDirectories(It.IsAny())).Returns(StandardSeries); + mock.Setup(c => c.Exists(It.Is(d => StandardSeries.Contains(d)))).Returns(true); + return mock.Object; } } } diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 95a681547..39440695a 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -41,7 +41,6 @@ ..\NzbDrone.Core\Libraries\log4net.dll - False Moq\Moq.dll @@ -55,13 +54,11 @@ ..\NzbDrone.Core\Libraries\SubSonic.Core.dll - - Libs\System.Data.SQLite.DLL - - - - + + Libs\System.Data.SQLite.DLL + True + ..\NzbDrone.Core\Libraries\TvdbLib.dll @@ -69,6 +66,7 @@ + @@ -77,7 +75,7 @@ - + @@ -99,7 +97,9 @@ PreserveNewest - + + Always + diff --git a/NzbDrone.Core.Test/SabControllerTest.cs b/NzbDrone.Core.Test/SabControllerTest.cs index 6a3060d0f..62bf4e57d 100644 --- a/NzbDrone.Core.Test/SabControllerTest.cs +++ b/NzbDrone.Core.Test/SabControllerTest.cs @@ -36,7 +36,7 @@ namespace NzbDrone.Core.Test var http = new Mock(); http.Setup(s => s.DownloadString("http://192.168.5.55:2222/sabnzbd/api?mode=addurl&name=http://www.nzbclub.com/nzb_download.aspx?mid=1950232&priority=0&cat=tv&nzbname=This+is+an+Nzb&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")).Returns("ok"); - var target = new SabProvider(config.Object, new Mock().Object, http.Object); + var target = new SabProvider(config.Object, http.Object); //Act bool result = target.AddByUrl("http://www.nzbclub.com/nzb_download.aspx?mid=1950232", "This is an Nzb"); @@ -65,7 +65,7 @@ namespace NzbDrone.Core.Test var http = new Mock(); http.Setup(s => s.DownloadString("http://192.168.5.55:2222/sabnzbd/api?mode=addurl&name=http://www.nzbclub.com/nzb_download.aspx?mid=1950232&priority=0&cat=tv&nzbname=This+is+an+Nzb&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")).Returns("error"); - var target = new SabProvider(config.Object, new Mock().Object, http.Object); + var target = new SabProvider(config.Object, http.Object); //Act bool result = target.AddByUrl("http://www.nzbclub.com/nzb_download.aspx?mid=1950232", "This is an Nzb"); @@ -98,7 +98,7 @@ namespace NzbDrone.Core.Test "http://192.168.5.55:2222/sabnzbd/api?mode=queue&output=xml&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) .Returns(new StreamReader(@".\Files\Queue.xml").ReadToEnd()); - var target = new SabProvider(config.Object, new Mock().Object, http.Object); + var target = new SabProvider(config.Object, http.Object); //Act bool result = target.IsInQueue("Ubuntu Test"); @@ -131,7 +131,7 @@ namespace NzbDrone.Core.Test "http://192.168.5.55:2222/sabnzbd/api?mode=queue&output=xml&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) .Returns(new StreamReader(@".\Files\QueueEmpty.xml").ReadToEnd()); - var target = new SabProvider(config.Object, new Mock().Object, http.Object); + var target = new SabProvider(config.Object, http.Object); //Act bool result = target.IsInQueue(String.Empty); @@ -164,7 +164,7 @@ namespace NzbDrone.Core.Test "http://192.168.5.55:2222/sabnzbd/api?mode=queue&output=xml&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass")) .Returns(new StreamReader(@".\Files\QueueError.xml").ReadToEnd()); - var target = new SabProvider(config.Object, new Mock().Object, http.Object); + var target = new SabProvider(config.Object, http.Object); //Act bool result = target.IsInQueue(String.Empty); diff --git a/NzbDrone.Core.Test/SeriesTest.cs b/NzbDrone.Core.Test/SeriesProviderTest.cs similarity index 67% rename from NzbDrone.Core.Test/SeriesTest.cs rename to NzbDrone.Core.Test/SeriesProviderTest.cs index b74edaa40..19a91ebf2 100644 --- a/NzbDrone.Core.Test/SeriesTest.cs +++ b/NzbDrone.Core.Test/SeriesProviderTest.cs @@ -12,6 +12,7 @@ using Ninject; using Ninject.Moq; using NzbDrone.Core.Providers; using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Episode; using SubSonic.Repository; using TvdbLib.Data; using System.Linq; @@ -20,7 +21,7 @@ using System.Linq; namespace NzbDrone.Core.Test { [TestFixture] - public class SeriesTest + public class SeriesProviderTest { [Test] public void Map_path_to_series() @@ -34,10 +35,10 @@ namespace NzbDrone.Core.Test var moqData = new Mock(); var moqTvdb = new Mock(); - moqData.Setup(f => f.Exists(c => c.TvdbId == It.IsAny())).Returns(false); + moqData.Setup(f => f.Exists(c => c.SeriesId == It.IsAny())).Returns(false); moqTvdb.Setup(f => f.GetSeries(It.IsAny())).Returns(fakeSearch); - moqTvdb.Setup(f => f.GetSeries(fakeSeries.Id, It.IsAny())).Returns(fakeSeries); + moqTvdb.Setup(f => f.GetSeries(fakeSeries.Id, false)).Returns(fakeSeries).Verifiable(); var kernel = new MockingKernel(); kernel.Bind().ToConstant(moqData.Object); @@ -49,6 +50,7 @@ namespace NzbDrone.Core.Test var mappedSeries = seriesController.MapPathToSeries(@"D:\TV Shows\The Simpsons"); //Assert + moqTvdb.VerifyAll(); Assert.AreEqual(fakeSeries, mappedSeries); } @@ -71,7 +73,7 @@ namespace NzbDrone.Core.Test { //Arrange var sonicRepo = MockLib.GetEmptyRepository(); - var series = Builder.CreateNew().With(c => c.TvdbId = tvdbId).Build(); + var series = Builder.CreateNew().With(c => c.SeriesId = tvdbId).Build(); //Act var addId = sonicRepo.Add(series); @@ -80,28 +82,43 @@ namespace NzbDrone.Core.Test Assert.AreEqual(tvdbId, addId); var allSeries = sonicRepo.All(); Assert.IsNotEmpty(allSeries); - Assert.AreEqual(tvdbId, allSeries.First().TvdbId); + Assert.AreEqual(tvdbId, allSeries.First().SeriesId); } [Test] - [Row(new object[] { "CAPITAL", "capital", true })] - [Row(new object[] { "Something!!", "Something", true })] - [Row(new object[] { "Simpsons 2000", "Simpsons", true })] - [Row(new object[] { "Simp222sons", "Simpsons", true })] - [Row(new object[] { "Simpsons", "The Simpsons", true })] - [Row(new object[] { "Law and order", "Law & order", true })] - [Row(new object[] { "xxAndxx", "xxxx", false })] - [Row(new object[] { "Andxx", "xx", false })] - [Row(new object[] { "xxAnd", "xx", false })] - [Row(new object[] { "Thexx", "xx", false })] - [Row(new object[] { "Thexx", "xx", false })] - [Row(new object[] { "xxThexx", "xxxxx", false })] - [Row(new object[] { "Simpsons The", "Simpsons", true })] - public void Name_match_test(string a, string b, bool match) + public void get_unmapped() { - bool result = TvDbProvider.IsTitleMatch(a, b); + //Setup + var kernel = new MockingKernel(); - Assert.AreEqual(match, result, "{0} , {1}", a, b); + + kernel.Bind().To(); + kernel.Bind().ToConstant(MockLib.GetStandardDisk()); + + var seriesController = kernel.Get(); + + //Act + var unmappedFolder = seriesController.GetUnmappedFolders(); + + //Assert + Assert.AreElementsEqualIgnoringOrder(MockLib.StandardSeries, unmappedFolder); + } + + [Test] + public void get_episode_test() + { + var fakeSeries = Builder.CreateNew().Build(); + var fakeEpisode = Builder.CreateNew().With(c => c.SeriesId).Build(); + + Console.WriteLine("test"); + + var repo = MockLib.GetEmptyRepository(); + repo.Add(fakeSeries); + repo.Add(fakeEpisode); + + var fetchedSeries = repo.Single(fakeSeries.SeriesId); + + Assert.IsNotEmpty(fetchedSeries.Episodes); } } } diff --git a/NzbDrone.Core.Test/TvDbControllerTest.cs b/NzbDrone.Core.Test/TvDbControllerTest.cs index e35b19cbc..82447975c 100644 --- a/NzbDrone.Core.Test/TvDbControllerTest.cs +++ b/NzbDrone.Core.Test/TvDbControllerTest.cs @@ -15,14 +15,77 @@ namespace NzbDrone.Core.Test [Row("The Simpsons")] [Row("Family Guy")] [Row("South Park")] - [Ignore("Have to find a way to mock app path for tests.")] - public void TestSearch(string title) + [Row("clone high, usa")] + public void successful_search(string title) { - var tvCont =new TvDbProvider(); + var tvCont = new TvDbProvider(); var result = tvCont.SearchSeries(title); - Assert.AreNotEqual(0, result.Count); + Assert.IsNotEmpty(result); Assert.AreEqual(title, result[0].SeriesName, StringComparison.InvariantCultureIgnoreCase); } + + [Test] + [Row("The Simpsons")] + [Row("Family Guy")] + [Row("South Park")] + public void successful_title_lookup(string title) + { + var tvCont = new TvDbProvider(); + var result = tvCont.GetSeries(title); + + Assert.AreEqual(title, result.SeriesName, StringComparison.InvariantCultureIgnoreCase); + } + + + [Test] + [Row(new object[] { "CAPITAL", "capital", true })] + [Row(new object[] { "Something!!", "Something", true })] + [Row(new object[] { "Simpsons 2000", "Simpsons", true })] + [Row(new object[] { "Simp222sons", "Simpsons", true })] + [Row(new object[] { "Simpsons", "The Simpsons", true })] + [Row(new object[] { "Law and order", "Law & order", true })] + [Row(new object[] { "xxAndxx", "xxxx", false })] + [Row(new object[] { "Andxx", "xx", false })] + [Row(new object[] { "xxAnd", "xx", false })] + [Row(new object[] { "Thexx", "xx", false })] + [Row(new object[] { "Thexx", "xx", false })] + [Row(new object[] { "xxThexx", "xxxxx", false })] + [Row(new object[] { "Simpsons The", "Simpsons", true })] + public void Name_match_test(string a, string b, bool match) + { + bool result = TvDbProvider.IsTitleMatch(a, b); + + Assert.AreEqual(match, result, "{0} , {1}", a, b); + } + + [Test] + public void no_search_result() + { + //setup + var tvdbProvider = new TvDbProvider(); + + //act + var result = tvdbProvider.SearchSeries("clone high"); + + //assert + Assert.IsEmpty(result); + } + + [Test] + public void no_result_title_lookup() + { + //setup + var tvdbProvider = new TvDbProvider(); + + //act + var result = tvdbProvider.GetSeries("clone high"); + + //assert + Assert.IsNull(result); + } + } + + } diff --git a/NzbDrone.Core/Main.cs b/NzbDrone.Core/CentralDispatch.cs similarity index 69% rename from NzbDrone.Core/Main.cs rename to NzbDrone.Core/CentralDispatch.cs index 4e193891b..8bd4ae1f5 100644 --- a/NzbDrone.Core/Main.cs +++ b/NzbDrone.Core/CentralDispatch.cs @@ -5,13 +5,15 @@ using Ninject; using NLog.Config; using NLog.Targets; using NzbDrone.Core.Providers; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Episode; using SubSonic.DataProviders; using SubSonic.Repository; using NLog; namespace NzbDrone.Core { - public static class Main + public static class CentralDispatch { public static void BindKernel(IKernel kernel) { @@ -19,16 +21,27 @@ namespace NzbDrone.Core var provider = ProviderFactory.GetProvider(connectionString, "System.Data.SQLite"); kernel.Bind().To(); + kernel.Bind().To(); + kernel.Bind().To(); kernel.Bind().To(); kernel.Bind().To(); - kernel.Bind().To(); - kernel.Bind().ToMethod(c => log4net.LogManager.GetLogger("logger-name")); - kernel.Bind().ToMethod(c => new SimpleRepository(provider, SimpleRepositoryOptions.RunMigrations)); + kernel.Bind().To().InSingletonScope(); + kernel.Bind().ToMethod(c => new SimpleRepository(provider, SimpleRepositoryOptions.RunMigrations)).InSingletonScope(); + + ForceMigration(kernel.Get()); } public static String AppPath { - get { return new DirectoryInfo(HttpContext.Current.Server.MapPath("\\")).FullName; } + get + { + if (HttpContext.Current != null) + { + return new DirectoryInfo(HttpContext.Current.Server.MapPath("\\")).FullName; + } + return Directory.GetCurrentDirectory(); + } + } @@ -67,5 +80,12 @@ namespace NzbDrone.Core logger.Error("error log message"); logger.Fatal("fatal log message"); } + + private static void ForceMigration(IRepository repository) + { + repository.GetPaged(0, 1); + repository.GetPaged(0, 1); + repository.GetPaged(0, 1); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index a13ed8a78..e6616b95b 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -125,7 +125,6 @@ False Libraries\Castle.Core.dll - @@ -157,16 +156,17 @@ + + + - - - + - + diff --git a/NzbDrone.Core/Providers/ConfigProvider.cs b/NzbDrone.Core/Providers/ConfigProvider.cs index 19f0bdc90..748cc06f2 100644 --- a/NzbDrone.Core/Providers/ConfigProvider.cs +++ b/NzbDrone.Core/Providers/ConfigProvider.cs @@ -1,5 +1,5 @@ using System; -using log4net; +using NLog; using NzbDrone.Core.Repository; using SubSonic.Repository; @@ -8,13 +8,11 @@ namespace NzbDrone.Core.Providers public class ConfigProvider : IConfigProvider { private const string SERIES_ROOTS = "SeriesRoots"; - private readonly ILog _logger; + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private readonly IRepository _sonicRepo; - public ConfigProvider(ILog logger, IRepository dataRepository) + public ConfigProvider(IRepository dataRepository) { - _logger = logger; - _sonicRepo = dataRepository; } @@ -39,7 +37,7 @@ namespace NzbDrone.Core.Providers if (dbValue != null && !String.IsNullOrEmpty(dbValue.Value)) return dbValue.Value; - _logger.WarnFormat("Unable to find config key '{0}' defaultValue:'{1}'", key, defaultValue); + Logger.Debug("Unable to find config key '{0}' defaultValue:'{1}'", key, defaultValue); if (makePermanent) SetValue(key, defaultValue.ToString()); value = defaultValue.ToString(); @@ -54,16 +52,17 @@ namespace NzbDrone.Core.Providers if (value == null) throw new ArgumentNullException("key"); - _logger.DebugFormat("Writing Setting to file. Key:'{0}' Value:'{1}'", key, value); + Logger.Debug("Writing Setting to file. Key:'{0}' Value:'{1}'", key, value); var dbValue = _sonicRepo.Single(key); if (dbValue == null) { - _sonicRepo.Add(new Config { - Key = key, - Value = value - }); + _sonicRepo.Add(new Config + { + Key = key, + Value = value + }); } else { diff --git a/NzbDrone.Core/Providers/EpisodeProvider.cs b/NzbDrone.Core/Providers/EpisodeProvider.cs index 0566f8201..13a63a227 100644 --- a/NzbDrone.Core/Providers/EpisodeProvider.cs +++ b/NzbDrone.Core/Providers/EpisodeProvider.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Text.RegularExpressions; +using NLog; using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Episode; using NzbDrone.Core.Repository.Quality; using SubSonic.Repository; @@ -27,12 +29,19 @@ namespace NzbDrone.Core.Providers private readonly IRepository _sonicRepo; - private readonly ISeriesProvider _seriesProvider; + private readonly ISeriesProvider _series; + private readonly ISeasonProvider _seasons; + private readonly ITvDbProvider _tvDb; + private static readonly Logger Logger = NLog.LogManager.GetCurrentClassLogger(); - public EpisodeProvider(IRepository sonicRepo, ISeriesProvider seriesProvider) + + public EpisodeProvider(IRepository sonicRepo, ISeriesProvider seriesProvider, ISeasonProvider seasonProvider, ITvDbProvider tvDbProvider) { _sonicRepo = sonicRepo; - _seriesProvider = seriesProvider; + _series = seriesProvider; + _tvDb = tvDbProvider; + _seasons = seasonProvider; + } public Episode GetEpisode(long id) @@ -40,7 +49,7 @@ namespace NzbDrone.Core.Providers throw new NotImplementedException(); } - public Episode SaveEpisode(Episode episode) + public Episode UpdateEpisode(Episode episode) { throw new NotImplementedException(); } @@ -57,7 +66,7 @@ namespace NzbDrone.Core.Providers public String GetSabTitle(Episode episode) { - var series = _seriesProvider.GetSeries(episode.SeriesId); + var series = _series.GetSeries(episode.SeriesId); if (series == null) throw new ArgumentException("Unknown series. ID: " + episode.SeriesId); //TODO: This method should return a standard title for the sab episode. @@ -75,6 +84,44 @@ namespace NzbDrone.Core.Providers throw new NotImplementedException(); } + public void RefreshSeries(int seriesId) + { + Logger.Info("Starting episode info refresh for series:{0}", seriesId); + int successCount = 0; + int failCount = 0; + var targetSeries = _tvDb.GetSeries(seriesId, true); + foreach (var episode in targetSeries.Episodes) + { + try + { + _seasons.EnsureSeason(seriesId, episode.SeasonId, episode.SeasonNumber); + var newEpisode = new EpisodeInfo() + { + AirDate = episode.FirstAired, + EpisodeId = episode.Id, + EpisodeNumber = episode.EpisodeNumber, + Language = episode.Language.Abbriviation, + Overview = episode.Overview, + SeasonId = episode.SeasonId, + SeasonNumber = episode.SeasonNumber, + SeriesId = episode.SeriesId, + Title = episode.EpisodeName + }; + + _sonicRepo.Add(newEpisode); + successCount++; + + } + catch (Exception e) + { + Logger.FatalException(String.Format("An error has occured while updating episode info for series {0}", seriesId), e); + failCount++; + } + } + + Logger.Info("Finished episode refresh for series:{0}. Success:{1} - Fail:{2} ", seriesId, successCount, failCount); + } + /// @@ -82,27 +129,25 @@ namespace NzbDrone.Core.Providers /// /// Title of the report /// List of episodes relating to the post - public static List Parse(string title) + public static List Parse(string title) { var match = ParseRegex.Match(title); if (!match.Success) throw new ArgumentException(String.Format("Title doesn't match any know patterns. [{0}]", title)); - var result = new List(); + var result = new List(); - result.Add(new Episode() { EpisodeNumber = Convert.ToInt32(match.Groups["episodeNumber"].Value) }); + result.Add(new RemoteEpisode { EpisodeNumber = Convert.ToInt32(match.Groups["episodeNumber"].Value) }); if (match.Groups["episodeNumber2"].Success) { - result.Add(new Episode() { EpisodeNumber = Convert.ToInt32(match.Groups["episodeNumber2"].Value) }); + result.Add(new RemoteEpisode { EpisodeNumber = Convert.ToInt32(match.Groups["episodeNumber2"].Value) }); } foreach (var ep in result) { - //TODO: Get TVDB episode Title, Series name and the rest of the details ep.SeasonNumber = Convert.ToInt32(match.Groups["seasonNumber"].Value); - ep.Title = ReplaceSeparatorChars(match.Groups["episodeName"].Value); ep.Proper = title.Contains("PROPER"); ep.Quality = QualityTypes.Unknown; } @@ -110,13 +155,5 @@ namespace NzbDrone.Core.Providers return result; } - private static string ReplaceSeparatorChars(string text) - { - if (text == null) - throw new ArgumentNullException("text"); - - return text.Replace('.', ' ').Replace('-', ' ').Replace('_', ' ').Trim(); - } - } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/IEpisodeProvider.cs b/NzbDrone.Core/Providers/IEpisodeProvider.cs index 2ce9b962c..4c55ea803 100644 --- a/NzbDrone.Core/Providers/IEpisodeProvider.cs +++ b/NzbDrone.Core/Providers/IEpisodeProvider.cs @@ -1,13 +1,14 @@ using System; using System.Collections.Generic; using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Episode; namespace NzbDrone.Core.Providers { public interface IEpisodeProvider { Episode GetEpisode(long id); - Episode SaveEpisode(Episode episode); + Episode UpdateEpisode(Episode episode); IList GetEpisodesBySeason(long seasonId); IList GetEpisodeBySeries(long seriesId); String GetSabTitle(Episode episode); @@ -18,5 +19,7 @@ namespace NzbDrone.Core.Providers /// Episode that needs to be checked /// bool IsNeeded(Episode episode); + + void RefreshSeries(int seriesId); } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/ISeasonProvider.cs b/NzbDrone.Core/Providers/ISeasonProvider.cs index dfd084ec8..6edc04892 100644 --- a/NzbDrone.Core/Providers/ISeasonProvider.cs +++ b/NzbDrone.Core/Providers/ISeasonProvider.cs @@ -5,10 +5,9 @@ namespace NzbDrone.Core.Providers { public interface ISeasonProvider { - Season GetSeason(long seasonId); - List GetSeasongs(long seriesId); - + Season GetSeason(int seasonId); + List GetSeasongs(int seriesId); + void EnsureSeason(int seriesId, int seasonId, int seasonNumber); int SaveSeason(Season season); } - } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/ISeriesProvider.cs b/NzbDrone.Core/Providers/ISeriesProvider.cs index 89ec8e783..9fbbe3468 100644 --- a/NzbDrone.Core/Providers/ISeriesProvider.cs +++ b/NzbDrone.Core/Providers/ISeriesProvider.cs @@ -9,7 +9,7 @@ namespace NzbDrone.Core.Providers public interface ISeriesProvider { IQueryable GetSeries(); - Series GetSeries(long tvdbId); + Series GetSeries(int seriesId); void SyncSeriesWithDisk(); /// diff --git a/NzbDrone.Core/Providers/ITvDbProvider.cs b/NzbDrone.Core/Providers/ITvDbProvider.cs index ca43e27be..70a852a20 100644 --- a/NzbDrone.Core/Providers/ITvDbProvider.cs +++ b/NzbDrone.Core/Providers/ITvDbProvider.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Providers public interface ITvDbProvider { IList SearchSeries(string name); - TvdbSeries GetSeries(int id, TvdbLanguage language); TvdbSearchResult GetSeries(string title); + TvdbSeries GetSeries(int id, bool loadEpisodes); } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/SabProvider.cs b/NzbDrone.Core/Providers/SabProvider.cs index 664c681a9..2b8bdbd72 100644 --- a/NzbDrone.Core/Providers/SabProvider.cs +++ b/NzbDrone.Core/Providers/SabProvider.cs @@ -2,20 +2,20 @@ using System.Linq; using System.Web; using System.Xml.Linq; -using log4net; +using NLog; namespace NzbDrone.Core.Providers { public class SabProvider : IDownloadProvider { private readonly IConfigProvider _config; - private readonly ILog _logger; private readonly IHttpProvider _http; - public SabProvider(IConfigProvider config, ILog logger, IHttpProvider http) + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public SabProvider(IConfigProvider config, IHttpProvider http) { _config = config; - _logger = logger; _http = http; } @@ -32,10 +32,10 @@ namespace NzbDrone.Core.Providers string action = string.Format("mode={0}&name={1}&priority={2}&cat={3}&nzbname={4}", mode, name, priority, cat, nzbName); string request = GetSabRequest(action); - _logger.DebugFormat("Adding report [{0}] to the queue.", nzbName); + Logger.Debug("Adding report [{0}] to the queue.", nzbName); string response = _http.DownloadString(request).Replace("\n", String.Empty); - _logger.DebugFormat("Queue Repsonse: [{0}]", response); + Logger.Debug("Queue Repsonse: [{0}]", response); if (response == "ok") return true; @@ -61,7 +61,7 @@ namespace NzbDrone.Core.Providers //Get the Count of Items in Queue where 'filename' is Equal to goodName, if not zero, return true (isInQueue))) if ((xDoc.Descendants("slot").Where(s => s.Element("filename").Value.Equals(title, StringComparison.InvariantCultureIgnoreCase))).Count() != 0) { - _logger.DebugFormat("Episode in queue - '{0}'", title); + Logger.Debug("Episode in queue - '{0}'", title); return true; } diff --git a/NzbDrone.Core/Providers/SeasonProvider.cs b/NzbDrone.Core/Providers/SeasonProvider.cs new file mode 100644 index 000000000..481207758 --- /dev/null +++ b/NzbDrone.Core/Providers/SeasonProvider.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using NLog; +using NzbDrone.Core.Repository; +using SubSonic.Repository; + +namespace NzbDrone.Core.Providers +{ + class SeasonProvider : ISeasonProvider + { + private readonly IRepository _sonicRepo; + private static readonly Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + + public SeasonProvider(IRepository dataRepository) + { + _sonicRepo = dataRepository; + } + + public Season GetSeason(int seasonId) + { + throw new NotImplementedException(); + } + + public List GetSeasongs(int seriesId) + { + throw new NotImplementedException(); + } + + public void EnsureSeason(int seriesId, int seasonId, int seasonNumber) + { + if (_sonicRepo.Exists(s => s.SeasonId == seasonId)) + return; + //TODO: Calculate Season Folder + Logger.Debug("Creating Season. SeriesID:{0} SeasonID:{1} SeasonNumber:{2} Folder:{3}", seriesId, seasonId, seasonNumber, string.Empty); + + var newSeason = new Season() + { + Folder = String.Empty, + Monitored = true, + SeasonId = seasonId, + SeasonNumber = seasonNumber, + SeriesId = seriesId + }; + _sonicRepo.Add(newSeason); + } + + + + public int SaveSeason(Season season) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Providers/SeriesProvider.cs b/NzbDrone.Core/Providers/SeriesProvider.cs index f0e86e082..34c279aa1 100644 --- a/NzbDrone.Core/Providers/SeriesProvider.cs +++ b/NzbDrone.Core/Providers/SeriesProvider.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; -using log4net; using NLog; using NzbDrone.Core.Repository; using SubSonic.Repository; @@ -38,7 +37,7 @@ namespace NzbDrone.Core.Providers private readonly IDiskProvider _diskProvider; private readonly IRepository _sonioRepo; private readonly ITvDbProvider _tvDb; - private static readonly Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Regex CleanUpRegex = new Regex(@"((\s|^)the(\s|$))|((\s|^)and(\s|$))|[^a-z]", RegexOptions.IgnoreCase | RegexOptions.Compiled); public SeriesProvider(IDiskProvider diskProvider, IConfigProvider configProvider, IRepository dataRepository, ITvDbProvider tvDbProvider) @@ -56,9 +55,9 @@ namespace NzbDrone.Core.Providers return _sonioRepo.All(); } - public Series GetSeries(long tvdbId) + public Series GetSeries(int seriesId) { - return _sonioRepo.Single(s => s.TvdbId == tvdbId); + return _sonioRepo.Single(s => s.SeriesId == seriesId); } /// @@ -68,7 +67,7 @@ namespace NzbDrone.Core.Providers /// Whether or not the show is monitored public bool IsMonitored(long id) { - return _sonioRepo.Exists(c => c.TvdbId == id && c.Monitored); + return _sonioRepo.Exists(c => c.SeriesId == id && c.Monitored); } /// @@ -99,16 +98,18 @@ namespace NzbDrone.Core.Providers if (mappedSeries == null) { Logger.Warn("Unable to find a matching series for '{0}'", seriesFolder); - break; - } - - if (!_sonioRepo.Exists(s => s.TvdbId == mappedSeries.Id)) - { - RegisterSeries(seriesFolder, mappedSeries); } else { - Logger.Warn("Folder '{0}' mapped to '{1}' which is already another folder assigned to it.'", seriesFolder, mappedSeries.SeriesName); + + if (!_sonioRepo.Exists(s => s.SeriesId == mappedSeries.Id)) + { + RegisterSeries(seriesFolder, mappedSeries); + } + else + { + Logger.Warn("Folder '{0}' mapped to '{1}' which is already another folder assigned to it.'", seriesFolder, mappedSeries.SeriesName); + } } } @@ -137,7 +138,7 @@ namespace NzbDrone.Core.Providers if (searchResults == null) return null; - return _tvDb.GetSeries(searchResults.Id, searchResults.Language); + return _tvDb.GetSeries(searchResults.Id, false); } @@ -145,7 +146,7 @@ namespace NzbDrone.Core.Providers { Logger.Info("registering '{0}' with [{1}]-{2}", path, series.Id, series.SeriesName); var repoSeries = new Series(); - repoSeries.TvdbId = series.Id; + repoSeries.SeriesId = series.Id; repoSeries.Title = series.SeriesName; repoSeries.AirTimes = series.AirsTime; repoSeries.AirsDayOfWeek = series.AirsDayOfWeek; diff --git a/NzbDrone.Core/Providers/TvDbProvider.cs b/NzbDrone.Core/Providers/TvDbProvider.cs index 18fd67d90..3cbc9edda 100644 --- a/NzbDrone.Core/Providers/TvDbProvider.cs +++ b/NzbDrone.Core/Providers/TvDbProvider.cs @@ -19,7 +19,7 @@ namespace NzbDrone.Core.Providers public TvDbProvider() { - _handler = new TvdbHandler(new XmlCacheProvider(Path.Combine(Main.AppPath, @"cache\tvdbcache.xml")), TVDB_APIKEY); + _handler = new TvdbHandler(new XmlCacheProvider(CentralDispatch.AppPath + @"\cache\tvdb"), TVDB_APIKEY); } #region ITvDbProvider Members @@ -44,13 +44,17 @@ namespace NzbDrone.Core.Providers public TvdbSearchResult GetSeries(string title) { - return SearchSeries(title)[0]; + var searchResults = SearchSeries(title); + if (searchResults.Count == 0) + return null; + + return searchResults[0]; } - public TvdbSeries GetSeries(int id, TvdbLanguage language) + public TvdbSeries GetSeries(int id, bool loadEpisodes) { - Logger.Debug("Fetching seriesId'{0}' - '{1}' from tvdb", id, language); - return _handler.GetSeries(id, language, true, false, false); + Logger.Debug("Fetching SeriesId'{0}' from tvdb", id); + return _handler.GetSeries(id, TvdbLanguage.DefaultLanguage, loadEpisodes, false, false); } /// diff --git a/NzbDrone.Core/Repository/Config.cs b/NzbDrone.Core/Repository/Config.cs index 42cf82435..898b69cf5 100644 --- a/NzbDrone.Core/Repository/Config.cs +++ b/NzbDrone.Core/Repository/Config.cs @@ -2,6 +2,7 @@ namespace NzbDrone.Core.Repository { + [SubSonicTableNameOverride("Config")] public class Config { [SubSonicPrimaryKey] diff --git a/NzbDrone.Core/Repository/Episode.cs b/NzbDrone.Core/Repository/Episode.cs deleted file mode 100644 index 199ea973b..000000000 --- a/NzbDrone.Core/Repository/Episode.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using NzbDrone.Core.Repository.Quality; -using SubSonic.SqlGeneration.Schema; - -namespace NzbDrone.Core.Repository -{ - public class Episode - { - [SubSonicPrimaryKey(false)] - public long EpisodeId { get; set; } - - public long SeriesId { get; set; } - public string Title { get; set; } - public long SeasonId { get; set; } - public int SeasonNumber { get; set; } - public int EpisodeNumber { get; set; } - public DateTime AirDate { get; set; } - public QualityTypes Quality { get; set; } - public bool Proper { get; set; } - - [SubSonicToOneRelation(ThisClassContainsJoinKey = true)] - public virtual Season Season { get; private set; } - - [SubSonicToOneRelation(ThisClassContainsJoinKey = true)] - public virtual Series Series { get; private set; } - } -} \ No newline at end of file diff --git a/NzbDrone.Core/Repository/Episode/Episode.cs b/NzbDrone.Core/Repository/Episode/Episode.cs new file mode 100644 index 000000000..49e9f8ae7 --- /dev/null +++ b/NzbDrone.Core/Repository/Episode/Episode.cs @@ -0,0 +1,16 @@ +using System; +using NzbDrone.Core.Repository.Quality; +using SubSonic.SqlGeneration.Schema; + +namespace NzbDrone.Core.Repository.Episode +{ + public class Episode + { + public virtual int SeriesId { get; set; } + public int SeasonNumber { get; set; } + public int EpisodeNumber { get; set; } + + [SubSonicToOneRelation(ThisClassContainsJoinKey = true)] + public virtual Series Series { get; private set; } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Repository/Episode/EpisodeInfo.cs b/NzbDrone.Core/Repository/Episode/EpisodeInfo.cs new file mode 100644 index 000000000..806ddf359 --- /dev/null +++ b/NzbDrone.Core/Repository/Episode/EpisodeInfo.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SubSonic.SqlGeneration.Schema; + +namespace NzbDrone.Core.Repository.Episode +{ + [SubSonicTableNameOverride("EpisodeInfo")] + public class EpisodeInfo : Episode + { + [SubSonicPrimaryKey(false)] + public virtual int EpisodeId { get; set; } + public int SeasonId { get; set; } + public string Title { get; set; } + public DateTime AirDate { get; set; } + [SubSonicLongString] + public string Overview { get; set; } + public string Language { get; set; } + + [SubSonicToOneRelation(ThisClassContainsJoinKey = true)] + public virtual Season Season { get; set; } + } +} diff --git a/NzbDrone.Core/Repository/Episode/RemoteEpisode.cs b/NzbDrone.Core/Repository/Episode/RemoteEpisode.cs new file mode 100644 index 000000000..ee09e806c --- /dev/null +++ b/NzbDrone.Core/Repository/Episode/RemoteEpisode.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.ServiceModel.Syndication; +using System.Text; +using NzbDrone.Core.Repository.Quality; +using SubSonic.SqlGeneration.Schema; + +namespace NzbDrone.Core.Repository.Episode +{ + public class RemoteEpisode : Episode + { + public QualityTypes Quality { get; set; } + public SyndicationItem Feed { get; set; } + public bool Proper { get; set; } + } +} diff --git a/NzbDrone.Core/Repository/LocalEpisode.cs b/NzbDrone.Core/Repository/LocalEpisode.cs deleted file mode 100644 index aec739b2a..000000000 --- a/NzbDrone.Core/Repository/LocalEpisode.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.ServiceModel.Syndication; -using SubSonic.SqlGeneration.Schema; - -namespace NzbDrone.Core.Repository -{ - public class LocalEpisode : Episode - { - public String Path { get; set; } - } -} \ No newline at end of file diff --git a/NzbDrone.Core/Repository/RemoteEpisode.cs b/NzbDrone.Core/Repository/RemoteEpisode.cs deleted file mode 100644 index c7bcd398e..000000000 --- a/NzbDrone.Core/Repository/RemoteEpisode.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.ServiceModel.Syndication; -using SubSonic.SqlGeneration.Schema; - -namespace NzbDrone.Core.Repository -{ - public class RemoteEpisode : Episode - { - [SubSonicIgnore] - public SyndicationItem Feed { get; set; } - } -} \ No newline at end of file diff --git a/NzbDrone.Core/Repository/Season.cs b/NzbDrone.Core/Repository/Season.cs index 2b795d2f5..e20331001 100644 --- a/NzbDrone.Core/Repository/Season.cs +++ b/NzbDrone.Core/Repository/Season.cs @@ -8,16 +8,16 @@ namespace NzbDrone.Core.Repository public class Season { [SubSonicPrimaryKey(false)] - public long SeasonId { get; set; } + public virtual long SeasonId { get; set; } public long SeriesId { get; set; } public int SeasonNumber { get; set; } public bool Monitored { get; set; } public string Folder { get; set; } [SubSonicToManyRelation] - public virtual List Episodes { get; set; } + public virtual List Episodes { get; private set; } [SubSonicToOneRelation(ThisClassContainsJoinKey = true)] - public virtual Series Series { get; set; } + public virtual Series Series { get; private set; } } } \ No newline at end of file diff --git a/NzbDrone.Core/Repository/Series.cs b/NzbDrone.Core/Repository/Series.cs index 82b42d753..2bb2e56a8 100644 --- a/NzbDrone.Core/Repository/Series.cs +++ b/NzbDrone.Core/Repository/Series.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using NzbDrone.Core.Repository.Episode; using SubSonic.SqlGeneration.Schema; namespace NzbDrone.Core.Repository @@ -7,7 +8,7 @@ namespace NzbDrone.Core.Repository public class Series { [SubSonicPrimaryKey(false)] - public int TvdbId { get; set; } + public virtual int SeriesId { get; set; } public string Title { get; set; } @@ -32,8 +33,8 @@ namespace NzbDrone.Core.Repository public virtual List Seasons { get; private set; } [SubSonicToManyRelation] - public virtual List Episodes { get; private set; } + public virtual List Episodes { get; private set; } + - } } \ No newline at end of file diff --git a/NzbDrone.Web/Controllers/SeriesController.cs b/NzbDrone.Web/Controllers/SeriesController.cs index 91a455ac7..76bec605e 100644 --- a/NzbDrone.Web/Controllers/SeriesController.cs +++ b/NzbDrone.Web/Controllers/SeriesController.cs @@ -10,12 +10,14 @@ namespace NzbDrone.Web.Controllers public class SeriesController : Controller { private readonly ISeriesProvider _seriesProvider; + private readonly IEpisodeProvider _episodeProvider; // // GET: /Series/ - public SeriesController(ISeriesProvider seriesProvider) + public SeriesController(ISeriesProvider seriesProvider, IEpisodeProvider episodeProvider) { _seriesProvider = seriesProvider; + _episodeProvider = episodeProvider; } public ActionResult Index() @@ -39,90 +41,23 @@ namespace NzbDrone.Web.Controllers } + public ActionResult LoadEpisodes(int seriesId) + { + _episodeProvider.RefreshSeries(seriesId); + return RedirectToAction("Details", new + { + seriesId = seriesId + }); + } + // // GET: /Series/Details/5 - public ActionResult Details(int tvdbId) + public ActionResult Details(int seriesId) { - return View(_seriesProvider.GetSeries(tvdbId)); + return View(_seriesProvider.GetSeries(seriesId)); } - // - // GET: /Series/Create - public ActionResult Create() - { - return View(); - } - - // - // POST: /Series/Create - - [HttpPost] - public ActionResult Create(FormCollection collection) - { - try - { - // TODO: Add insert logic here - - return RedirectToAction("Index"); - } - catch - { - return View(); - } - } - - // - // GET: /Series/Edit/5 - - public ActionResult Edit(int id) - { - return View(); - } - - // - // POST: /Series/Edit/5 - - [HttpPost] - public ActionResult Edit(int id, FormCollection collection) - { - try - { - // TODO: Add update logic here - - return RedirectToAction("Index"); - } - catch - { - return View(); - } - } - - // - // GET: /Series/Delete/5 - - public ActionResult Delete(int id) - { - return View(); - } - - // - // POST: /Series/Delete/5 - - [HttpPost] - public ActionResult Delete(int id, FormCollection collection) - { - try - { - // TODO: Add delete logic here - - return RedirectToAction("Index"); - } - catch - { - return View(); - } - } } } diff --git a/NzbDrone.Web/Global.asax.cs b/NzbDrone.Web/Global.asax.cs index ddee277b4..4b0b61353 100644 --- a/NzbDrone.Web/Global.asax.cs +++ b/NzbDrone.Web/Global.asax.cs @@ -27,7 +27,7 @@ namespace NzbDrone.Web protected override void OnApplicationStarted() { - Main.ConfigureNlog(); + CentralDispatch.ConfigureNlog(); AreaRegistration.RegisterAllAreas(); RegisterRoutes(RouteTable.Routes); base.OnApplicationStarted(); @@ -36,7 +36,7 @@ namespace NzbDrone.Web protected override IKernel CreateKernel() { _kernel = new StandardKernel(); - Main.BindKernel(_kernel); + CentralDispatch.BindKernel(_kernel); return _kernel; } diff --git a/NzbDrone.Web/Views/Series/Details.aspx b/NzbDrone.Web/Views/Series/Details.aspx index 9ca07d49b..0052d81ce 100644 --- a/NzbDrone.Web/Views/Series/Details.aspx +++ b/NzbDrone.Web/Views/Series/Details.aspx @@ -1,35 +1,52 @@ <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> +<%@ Import Namespace="Telerik.Web.Mvc.UI" %> - <%: Model.Title %> + <%: Model.Title %> -
- -
ID
-
<%: Model.TvdbId %>
- -
Overview
-
<%: Model.Overview %>
- -
Status
-
<%: Model.Status %>
- -
AirTimes
-
<%: Model.AirTimes %>
- -
Language
-
<%: Model.Language.ToUpper() %>
- -
Location
-
<%: Model.Path %>
- +
+ ID
+
+ <%: Model.SeriesId %>
+
+ Overview
+
+ <%: Model.Overview %>
+
+ Status
+
+ <%: Model.Status %>
+
+ AirTimes
+
+ <%: Model.AirTimes %>
+
+ Language
+
+ <%: Model.Language.ToUpper() %>
+
+ Location
+
+ <%: Model.Path %>
+ <%= Html.Telerik().Grid(Model.Episodes) + .Name("Episodes") + .Columns(columns => + { + columns.Bound(c => c.EpisodeNumber).Width(10); + columns.Bound(c => c.Title); + columns.Bound(c => c.AirDate).Format("{0:d}").Width(150); + }) + .Groupable(grouping => grouping.Groups(groups => groups.Add(c => c.SeasonNumber))) + .Sortable(rows=>rows + .OrderBy(epSort => epSort.Add(c => c.EpisodeNumber))) + + %>

- <%-- <%: Html.ActionLink("Edit", "Edit", new { /* id=Model.PrimaryKey */ }) %> |--%> + <%-- <%: Html.ActionLink("Edit", "Edit", new { /* id=Model.PrimaryKey */ }) %> |--%> <%: Html.ActionLink("Back to List", "Index") %> + <%: Html.ActionLink("Load Episodes", "LoadEpisodes", new{seriesId= Model.SeriesId}) %>

-
- diff --git a/NzbDrone.Web/Views/Series/index.aspx b/NzbDrone.Web/Views/Series/index.aspx index 2b2c3bf66..1b09b0726 100644 --- a/NzbDrone.Web/Views/Series/index.aspx +++ b/NzbDrone.Web/Views/Series/index.aspx @@ -20,11 +20,11 @@ .Name("Grid") .Columns(columns => { - columns.Bound(o => o.TvdbId).Width(100); + columns.Bound(o => o.SeriesId).Width(100); columns.Template(c => { %> - <%:Html.ActionLink(c.Title, "Details", new {tvdbId =c.TvdbId}) %> + <%:Html.ActionLink(c.Title, "Details", new {seriesId =c.SeriesId}) %> <% }).Title("Title"); columns.Bound(o => o.Status);