diff --git a/NzbDrone.Core.Test/HistoryTests/HistoryRepositoryFixture.cs b/NzbDrone.Core.Test/HistoryTests/HistoryRepositoryFixture.cs index b71d2d066..4ccc2364b 100644 --- a/NzbDrone.Core.Test/HistoryTests/HistoryRepositoryFixture.cs +++ b/NzbDrone.Core.Test/HistoryTests/HistoryRepositoryFixture.cs @@ -3,8 +3,6 @@ using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.History; -using NzbDrone.Core.Qualities; -using NzbDrone.Core.Tv; using NzbDrone.Core.Test.Framework; namespace NzbDrone.Core.Test.HistoryTests @@ -30,5 +28,18 @@ namespace NzbDrone.Core.Test.HistoryTests AllStoredModels.Should().HaveCount(10); AllStoredModels.Should().OnlyContain(s => s.Date > DateTime.Now.AddDays(-30)); } + + [Test] + public void should_read_write_dictionary() + { + var history = Builder.CreateNew().BuildNew(); + + history.Data.Add("key1","value1"); + history.Data.Add("key2","value2"); + + Subject.Insert(history); + + StoredModel.Data.Should().HaveCount(2); + } } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/MediaFileTests/MediaFileRepositoryFixture.cs b/NzbDrone.Core.Test/MediaFileTests/MediaFileRepositoryFixture.cs index 1e6a08d45..e727a4a6f 100644 --- a/NzbDrone.Core.Test/MediaFileTests/MediaFileRepositoryFixture.cs +++ b/NzbDrone.Core.Test/MediaFileTests/MediaFileRepositoryFixture.cs @@ -34,28 +34,6 @@ namespace NzbDrone.Core.Test.MediaFileTests } - [Test] - public void get_files_by_season() - { - var files = Builder.CreateListOfSize(20) - .All() - .With(c => c.Id = 0) - .With(s => s.SeasonNumber = 10) - .TheFirst(10) - .With(c => c.SeriesId = 1) - .TheNext(10) - .With(c => c.SeriesId = 2) - .Random(10) - .With(s => s.SeasonNumber = 20) - .Build(); - - - Db.InsertMany(files); - - - Subject.GetFilesBySeason(1, 20).Should().OnlyContain(c => c.SeriesId == 1 && c.SeasonNumber == 20); - } - [Test] public void GetFileByPath_should_return_null_if_file_does_not_exist_in_database() diff --git a/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/DropFolderImportServiceFixture.cs b/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/DropFolderImportServiceFixture.cs index 5c7127efa..1ad44dfd4 100644 --- a/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/DropFolderImportServiceFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/PostDownloadProviderTests/DropFolderImportServiceFixture.cs @@ -58,7 +58,7 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests [Test] public void should_import_file() { - Subject.ProcessDownloadedEpiosdesFolder(); + Subject.ProcessDownloadedEpisodesFolder(); VerifyImport(); } @@ -68,7 +68,7 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests { WithRecentFolderWrite(); - Subject.ProcessDownloadedEpiosdesFolder(); + Subject.ProcessDownloadedEpisodesFolder(); VerifyNoImport(); } @@ -78,7 +78,7 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests { WithOldWrite(); - Subject.ProcessDownloadedEpiosdesFolder(); + Subject.ProcessDownloadedEpisodesFolder(); Mocker.GetMock().Verify(c => c.GetSeries("foldername"), Times.Once()); @@ -90,7 +90,7 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests Mocker.GetMock().Setup(c => c.ImportFile(It.IsAny(), It.IsAny())) .Returns(_fakeEpisodeFile); - Subject.ProcessDownloadedEpiosdesFolder(); + Subject.ProcessDownloadedEpisodesFolder(); Mocker.GetMock().Verify(c => c.MoveEpisodeFile(_fakeEpisodeFile, true), Times.Once()); } @@ -101,7 +101,7 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests Mocker.GetMock().Setup(c => c.ImportFile(It.IsAny(), It.IsAny())) .Returns(null); - Subject.ProcessDownloadedEpiosdesFolder(); + Subject.ProcessDownloadedEpisodesFolder(); Mocker.GetMock().Verify(c => c.MoveEpisodeFile(It.IsAny(), It.IsAny()), Times.Never()); } @@ -113,7 +113,7 @@ namespace NzbDrone.Core.Test.ProviderTests.PostDownloadProviderTests Mocker.GetMock().Setup(c => c.IsFileLocked(It.IsAny())) .Returns(true); - Subject.ProcessDownloadedEpiosdesFolder(); + Subject.ProcessDownloadedEpisodesFolder(); VerifyNoImport(); } diff --git a/NzbDrone.Core/Datastore/Migration/004_updated_history.cs b/NzbDrone.Core/Datastore/Migration/004_updated_history.cs new file mode 100644 index 000000000..45449881c --- /dev/null +++ b/NzbDrone.Core/Datastore/Migration/004_updated_history.cs @@ -0,0 +1,24 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Tags("")] + [Migration(4)] + public class updated_history : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Delete.Table("History"); + + + Create.TableForModel("History") + .WithColumn("EpisodeId").AsInt32() + .WithColumn("SeriesId").AsInt32() + .WithColumn("SourceTitle").AsString() + .WithColumn("Date").AsDateTime() + .WithColumn("Quality").AsString() + .WithColumn("Data").AsString(); + } + } +} diff --git a/NzbDrone.Core/Datastore/TableMapping.cs b/NzbDrone.Core/Datastore/TableMapping.cs index e461dbf5c..520c26e1f 100644 --- a/NzbDrone.Core/Datastore/TableMapping.cs +++ b/NzbDrone.Core/Datastore/TableMapping.cs @@ -40,9 +40,9 @@ namespace NzbDrone.Core.Datastore Mapper.Entity().RegisterModel("History") .Relationships .AutoMapICollectionOrComplexProperties(); -// .Relationship(); -// .HasOne(h => h.Episode, h => h.EpisodeId) -// .HasOne(h => h.Series, h => h.SeriesId); + // .Relationship(); + // .HasOne(h => h.Episode, h => h.EpisodeId) + // .HasOne(h => h.Series, h => h.SeriesId); Mapper.Entity().RegisterModel("Series") .Ignore(s => s.RootFolderPath) @@ -79,6 +79,7 @@ namespace NzbDrone.Core.Datastore MapRepository.Instance.RegisterTypeConverter(typeof(Boolean), new BooleanIntConverter()); MapRepository.Instance.RegisterTypeConverter(typeof(Enum), new EnumIntConverter()); MapRepository.Instance.RegisterTypeConverter(typeof(Quality), new QualityIntConverter()); + MapRepository.Instance.RegisterTypeConverter(typeof(Dictionary), new EmbeddedDocumentConverter()); } private static void RegisterEmbeddedConverter() diff --git a/NzbDrone.Core/History/History.cs b/NzbDrone.Core/History/History.cs index dec9eec7a..76d2ed379 100644 --- a/NzbDrone.Core/History/History.cs +++ b/NzbDrone.Core/History/History.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using Marr.Data; using NzbDrone.Core.Datastore; using NzbDrone.Core.Tv; @@ -8,16 +7,21 @@ namespace NzbDrone.Core.History { public class History : ModelBase { + public History() + { + Data = new Dictionary(); + } + public int EpisodeId { get; set; } public int SeriesId { get; set; } - public string NzbTitle { get; set; } + public string SourceTitle { get; set; } public QualityModel Quality { get; set; } public DateTime Date { get; set; } - public string Indexer { get; set; } - public string NzbInfoUrl { get; set; } - public string ReleaseGroup { get; set; } public Episode Episode { get; set; } public Series Series { get; set; } + + public Dictionary Data { get; set; } } + } \ No newline at end of file diff --git a/NzbDrone.Core/History/HistoryService.cs b/NzbDrone.Core/History/HistoryService.cs index 7bbda0e41..45c4596f7 100644 --- a/NzbDrone.Core/History/HistoryService.cs +++ b/NzbDrone.Core/History/HistoryService.cs @@ -5,6 +5,7 @@ using NLog; using NzbDrone.Common.Messaging; using NzbDrone.Core.Datastore; using NzbDrone.Core.Download; +using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.Tv; namespace NzbDrone.Core.History @@ -18,7 +19,7 @@ namespace NzbDrone.Core.History PagingSpec Paged(PagingSpec pagingSpec); } - public class HistoryService : IHistoryService, IHandle + public class HistoryService : IHistoryService, IHandle, IHandle { private readonly IHistoryRepository _historyRepository; private readonly Logger _logger; @@ -61,15 +62,34 @@ namespace NzbDrone.Core.History var history = new History { Date = DateTime.Now, - Indexer = message.Episode.Report.Indexer, Quality = message.Episode.ParsedEpisodeInfo.Quality, - NzbTitle = message.Episode.Report.Title, + SourceTitle = message.Episode.Report.Title, SeriesId = episode.SeriesId, EpisodeId = episode.Id, - NzbInfoUrl = message.Episode.Report.NzbInfoUrl, - ReleaseGroup = message.Episode.Report.ReleaseGroup, }; + history.Data.Add("Indexer", message.Episode.Report.Indexer); + history.Data.Add("NzbInfoUrl", message.Episode.Report.NzbInfoUrl); + history.Data.Add("ReleaseGroup", message.Episode.Report.ReleaseGroup); + history.Data.Add("Age", message.Episode.Report.Age.ToString()); + + _historyRepository.Insert(history); + } + } + + public void Handle(EpisodeImportedEvent message) + { + foreach (var episode in message.EpisodeFile.Episodes.Value) + { + var history = new History + { + Date = DateTime.Now, + Quality = message.EpisodeFile.Quality, + SourceTitle = message.EpisodeFile.Path, + SeriesId = message.EpisodeFile.SeriesId, + EpisodeId = episode.Id, + }; + _historyRepository.Insert(history); } } diff --git a/NzbDrone.Core/MediaFiles/DownloadedEpisodesImportService.cs b/NzbDrone.Core/MediaFiles/DownloadedEpisodesImportService.cs index 85cf06534..6b956f0db 100644 --- a/NzbDrone.Core/MediaFiles/DownloadedEpisodesImportService.cs +++ b/NzbDrone.Core/MediaFiles/DownloadedEpisodesImportService.cs @@ -5,6 +5,7 @@ using NzbDrone.Common; using NzbDrone.Common.Messaging; using NzbDrone.Core.Configuration; using NzbDrone.Core.MediaFiles.Commands; +using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.Parser; using NzbDrone.Core.Tv; @@ -18,6 +19,7 @@ namespace NzbDrone.Core.MediaFiles private readonly IMoveEpisodeFiles _episodeFileMover; private readonly IParsingService _parsingService; private readonly IConfigService _configService; + private readonly IMessageAggregator _messageAggregator; private readonly Logger _logger; public DownloadedEpisodesImportService(IDiskProvider diskProvider, @@ -26,6 +28,7 @@ namespace NzbDrone.Core.MediaFiles IMoveEpisodeFiles episodeFileMover, IParsingService parsingService, IConfigService configService, + IMessageAggregator messageAggregator, Logger logger) { _diskProvider = diskProvider; @@ -34,10 +37,11 @@ namespace NzbDrone.Core.MediaFiles _episodeFileMover = episodeFileMover; _parsingService = parsingService; _configService = configService; + _messageAggregator = messageAggregator; _logger = logger; } - public void ProcessDownloadedEpiosdesFolder() + public void ProcessDownloadedEpisodesFolder() { //TODO: We should also process the download client's category folder var downloadedEpisodesFolder = _configService.DownloadedEpisodesFolder; @@ -135,11 +139,13 @@ namespace NzbDrone.Core.MediaFiles { _episodeFileMover.MoveEpisodeFile(episodeFile, true); } + + _messageAggregator.PublishEvent(new EpisodeImportedEvent(episodeFile)); } public void Execute(DownloadedEpisodesScanCommand message) { - ProcessDownloadedEpiosdesFolder(); + ProcessDownloadedEpisodesFolder(); } } } \ No newline at end of file diff --git a/NzbDrone.Core/MediaFiles/Events/EpisodeImportedEvent.cs b/NzbDrone.Core/MediaFiles/Events/EpisodeImportedEvent.cs new file mode 100644 index 000000000..e9d0eb458 --- /dev/null +++ b/NzbDrone.Core/MediaFiles/Events/EpisodeImportedEvent.cs @@ -0,0 +1,14 @@ +using NzbDrone.Common.Messaging; + +namespace NzbDrone.Core.MediaFiles.Events +{ + public class EpisodeImportedEvent:IEvent + { + public EpisodeFile EpisodeFile { get; private set; } + + public EpisodeImportedEvent(EpisodeFile episodeFile) + { + EpisodeFile = episodeFile; + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/MediaFiles/MediaFileRepository.cs b/NzbDrone.Core/MediaFiles/MediaFileRepository.cs index d3ba7c0d6..2e9415b99 100644 --- a/NzbDrone.Core/MediaFiles/MediaFileRepository.cs +++ b/NzbDrone.Core/MediaFiles/MediaFileRepository.cs @@ -9,7 +9,6 @@ namespace NzbDrone.Core.MediaFiles { EpisodeFile GetFileByPath(string path); List GetFilesBySeries(int seriesId); - List GetFilesBySeason(int seriesId, int seasonNumber); bool Exists(string path); } @@ -37,10 +36,5 @@ namespace NzbDrone.Core.MediaFiles return Query.Where(c => c.SeriesId == seriesId).ToList(); } - public List GetFilesBySeason(int seriesId, int seasonNumber) - { - return Query.Where(c => c.SeriesId == seriesId && c.SeasonNumber == seasonNumber).ToList(); - - } } } \ No newline at end of file diff --git a/NzbDrone.Core/MediaFiles/MediaFileService.cs b/NzbDrone.Core/MediaFiles/MediaFileService.cs index 931ada125..a5f3d6774 100644 --- a/NzbDrone.Core/MediaFiles/MediaFileService.cs +++ b/NzbDrone.Core/MediaFiles/MediaFileService.cs @@ -17,7 +17,6 @@ namespace NzbDrone.Core.MediaFiles bool Exists(string path); EpisodeFile GetFileByPath(string path); List GetFilesBySeries(int seriesId); - List GetFilesBySeason(int seriesId, int seasonNumber); } public class MediaFileService : IMediaFileService, IHandleAsync @@ -68,11 +67,6 @@ namespace NzbDrone.Core.MediaFiles return _mediaFileRepository.GetFilesBySeries(seriesId); } - public List GetFilesBySeason(int seriesId, int seasonNumber) - { - return _mediaFileRepository.GetFilesBySeason(seriesId, seasonNumber); - } - public void HandleAsync(SeriesDeletedEvent message) { var files = GetFilesBySeries(message.Series.Id); diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 49ca56a47..c0cf5a09a 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -209,6 +209,7 @@ + @@ -259,6 +260,7 @@ + diff --git a/UI/Shared/Cells/ToggleCell.js b/UI/Shared/Cells/ToggleCell.js new file mode 100644 index 000000000..4fb9c06ed --- /dev/null +++ b/UI/Shared/Cells/ToggleCell.js @@ -0,0 +1,34 @@ +"use strict"; + +define(['app', 'Episode/Layout'], function () { + NzbDrone.Series.Details.EpisodeIgnoreCell = Backgrid.Cell.extend({ + + className: 'episode-status-cell', + + render: function () { + this.$el.empty(); + + if (this.model) { + + var icon; + + if (this.model.get('episodeFile')) { + icon = 'icon-ok'; + + } + else { + if (this.model.get('hasAired')) { + icon = 'icon-warning-sign'; + } + else { + icon = 'icon-time'; + } + } + + this.$el.html(''.format(icon)); + } + + return this; + } + }); +});