diff --git a/NzbDrone.Core.Test/EpisodeProviderTest.cs b/NzbDrone.Core.Test/EpisodeProviderTest.cs index 03e12b013..8e3e5672f 100644 --- a/NzbDrone.Core.Test/EpisodeProviderTest.cs +++ b/NzbDrone.Core.Test/EpisodeProviderTest.cs @@ -991,5 +991,117 @@ namespace NzbDrone.Core.Test mocker.VerifyAllMocks(); } + + [Test] + public void IgnoreEpisode_Ignore() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(); + mocker.SetConstant(db); + + var episodes = Builder.CreateListOfSize(4) + .WhereAll() + .Have(c => c.SeriesId = 10) + .Have(c => c.SeasonNumber = 1) + .Have(c => c.Ignored = false) + .Build().ToList(); + + episodes.ForEach(c => db.Insert(c)); + + //Act + mocker.Resolve().SetEpisodeIgnore(1, true); + + //Assert + var episodesInDb = db.Fetch(@"SELECT * FROM Episodes"); + + episodesInDb.Should().HaveCount(4); + episodesInDb.Where(e => e.Ignored).Should().HaveCount(1); + + mocker.VerifyAllMocks(); + } + + [Test] + public void IgnoreEpisode_RemoveIgnore() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(); + mocker.SetConstant(db); + + var episodes = Builder.CreateListOfSize(4) + .WhereAll() + .Have(c => c.SeriesId = 10) + .Have(c => c.SeasonNumber = 1) + .Have(c => c.Ignored = true) + .Build().ToList(); + + episodes.ForEach(c => db.Insert(c)); + + //Act + mocker.Resolve().SetEpisodeIgnore(1, false); + + //Assert + var episodesInDb = db.Fetch(@"SELECT * FROM Episodes"); + + episodesInDb.Should().HaveCount(4); + episodesInDb.Where(e => !e.Ignored).Should().HaveCount(1); + + mocker.VerifyAllMocks(); + } + + [Test] + public void IgnoreSeason_Ignore() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(); + mocker.SetConstant(db); + + var episodes = Builder.CreateListOfSize(4) + .WhereAll() + .Have(c => c.SeriesId = 10) + .Have(c => c.SeasonNumber = 1) + .Have(c => c.Ignored = false) + .Build().ToList(); + + episodes.ForEach(c => db.Insert(c)); + + //Act + mocker.Resolve().SetSeasonIgnore(10, 1, true); + + //Assert + var episodesInDb = db.Fetch(@"SELECT * FROM Episodes"); + + episodesInDb.Should().HaveCount(4); + episodesInDb.Where(e => e.Ignored).Should().HaveCount(4); + + mocker.VerifyAllMocks(); + } + + [Test] + public void IgnoreSeason_RemoveIgnore() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(); + mocker.SetConstant(db); + + var episodes = Builder.CreateListOfSize(4) + .WhereAll() + .Have(c => c.SeriesId = 10) + .Have(c => c.SeasonNumber = 1) + .Have(c => c.Ignored = true) + .Build().ToList(); + + episodes.ForEach(c => db.Insert(c)); + + //Act + mocker.Resolve().SetSeasonIgnore(10, 1, false); + + //Assert + var episodesInDb = db.Fetch(@"SELECT * FROM Episodes"); + + episodesInDb.Should().HaveCount(4); + episodesInDb.Where(e => !e.Ignored).Should().HaveCount(4); + + mocker.VerifyAllMocks(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/EpisodeProvider.cs b/NzbDrone.Core/Providers/EpisodeProvider.cs index 416def223..0e8f7ea4f 100644 --- a/NzbDrone.Core/Providers/EpisodeProvider.cs +++ b/NzbDrone.Core/Providers/EpisodeProvider.cs @@ -296,26 +296,23 @@ namespace NzbDrone.Core.Providers public virtual void SetSeasonIgnore(long seriesId, int seasonNumber, bool isIgnored) { Logger.Info("Setting ignore flag on Series:{0} Season:{1} to {2}", seriesId, seasonNumber, isIgnored); - var episodes = GetEpisodesBySeason(seriesId, seasonNumber); - using (var tran = _database.GetTransaction()) - { - foreach (var episode in episodes) - { - episode.Ignored = isIgnored; - _database.Update(episode); - } - - //Shouldn't run if Database is a mock since transaction will be null - if (_database.GetType().Namespace != "Castle.Proxies" && tran != null) - { - tran.Complete(); - } + _database.Execute(@"UPDATE Episodes SET Ignored = @0 + WHERE SeriesId = @1 AND SeasonNumber = @2", + isIgnored, seriesId, seasonNumber); Logger.Info("Ignore flag for Series:{0} Season:{1} successfully set to {2}", seriesId, seasonNumber, isIgnored); - } + } + + public virtual void SetEpisodeIgnore(int episodeId, bool isIgnored) + { + Logger.Info("Setting ignore flag on Episode:{0} to {1}", episodeId, isIgnored); + _database.Execute(@"UPDATE Episodes SET Ignored = @0 + WHERE EpisodeId = @1", + isIgnored, episodeId); + Logger.Info("Ignore flag for Episode:{0} successfully set to {1}", episodeId, isIgnored); } public IList AttachSeries(IList episodes) diff --git a/NzbDrone.Web/Content/Images/ignored.png b/NzbDrone.Web/Content/Images/ignored.png index 06b5934d6..41423bad2 100644 Binary files a/NzbDrone.Web/Content/Images/ignored.png and b/NzbDrone.Web/Content/Images/ignored.png differ diff --git a/NzbDrone.Web/Controllers/SeriesController.cs b/NzbDrone.Web/Controllers/SeriesController.cs index 195fce36b..59566e3bb 100644 --- a/NzbDrone.Web/Controllers/SeriesController.cs +++ b/NzbDrone.Web/Controllers/SeriesController.cs @@ -148,12 +148,17 @@ namespace NzbDrone.Web.Controllers } [HttpPost] - public JsonResult SaveSeason(int seriesId, int seasonNumber, bool monitored) + public JsonResult SaveSeasonIgnore(int seriesId, int seasonNumber, bool ignored) { - if (_episodeProvider.IsIgnored(seriesId, seasonNumber) == monitored) - { - _episodeProvider.SetSeasonIgnore(seriesId, seasonNumber, !monitored); - } + _episodeProvider.SetSeasonIgnore(seriesId, seasonNumber, ignored); + + return new JsonResult { Data = "ok" }; + } + + [HttpPost] + public JsonResult SaveEpisodeIgnore(int episodeId, bool ignored) + { + _episodeProvider.SetEpisodeIgnore(episodeId, ignored); return new JsonResult { Data = "ok" }; } diff --git a/NzbDrone.Web/Scripts/seriesDetails.js b/NzbDrone.Web/Scripts/seriesDetails.js index cc18320cb..36544f364 100644 --- a/NzbDrone.Web/Scripts/seriesDetails.js +++ b/NzbDrone.Web/Scripts/seriesDetails.js @@ -1,5 +1,8 @@ var notIgnoredImage = '../../Content/Images/notIgnored.png'; var ignoredImage = '../../Content/Images/ignored.png'; +var seriesId = 0; +var saveSeasonIgnoreUrl = '../Series/SaveSeasonIgnore'; +var saveEpisodeIgnoreUrl = '../Series/SaveEpisodeIgnore'; $(".ignoreEpisode").live("click", function () { var toggle = $(this); @@ -15,17 +18,31 @@ $(".ignoreEpisode").live("click", function () { toggle.attr('src', ignoredImage); } + var seasonNumber = 0; + + //Flip the ignored to the new state (We want the new value moving forward) + ignored = !ignored; + if (toggle.hasClass('ignoredEpisodesMaster')) { - var seasonNumber = toggle.attr('id').replace('master_', ''); + seasonNumber = toggle.attr('id').replace('master_', ''); toggleChildren(seasonNumber, ignored); + saveSeasonIgnore(seasonNumber, ignored); + } + + else { + //Check to see if this is the last one ignored or the first not ignored + seasonNumber = toggle.attr('class').split(/\s+/)[1].replace('ignoreEpisode_', ''); + var episodeId = toggle.attr('id'); + toggleMaster(seasonNumber, ignored); + saveEpisodeIgnore(episodeId, ignored); } }); function toggleChildren(seasonNumber, ignored) { var ignoreEpisodes = $('.ignoreEpisode_' + seasonNumber); - if (!ignored) { + if (ignored) { ignoreEpisodes.each(function (index) { $(this).addClass('ignored'); $(this).attr('src', ignoredImage); @@ -37,9 +54,26 @@ function toggleChildren(seasonNumber, ignored) { $(this).removeClass('ignored'); $(this).attr('src', notIgnoredImage); }); - } + } } +function toggleMaster(seasonNumber) { + var ignoreEpisodes = $('.ignoreEpisode_' + seasonNumber); + var ignoredCount = ignoreEpisodes.filter('.ignored').length; + var master = $('#master_' + seasonNumber); + + if (ignoreEpisodes.length == ignoredCount) { + master.attr('src', ignoredImage); + master.addClass('ignored'); + } + + else { + master.attr('src', notIgnoredImage); + master.removeClass('ignored'); + } +} + +//Functions called by the Telerik Season Grid function grid_rowBound(e) { var dataItem = e.dataItem; var ignored = dataItem.Ignored; @@ -55,6 +89,9 @@ function grid_rowBound(e) { ignoredIcon.attr('src', notIgnoredImage); ignoredIcon.removeClass('ignored'); } + + if (seriesId == 0) + seriesId = dataItem.SeriesId } function grid_dataBound(e) { @@ -63,13 +100,7 @@ function grid_dataBound(e) { var ignoreEpisodes = $('.ignoreEpisode_' + seasonNumber); var master = $('#master_' + seasonNumber); var count = ignoreEpisodes.length; - var ignoredCount = 0; - - ignoreEpisodes.each(function (index) { - if ($(this).hasClass('ignored')) { - ignoredCount++; - } - }); + var ignoredCount = ignoreEpisodes.filter('.ignored').length; if (ignoredCount == count) { master.attr('src', ignoredImage); @@ -80,4 +111,26 @@ function grid_dataBound(e) { master.attr('src', notIgnoredImage); master.removeClass('ignored'); } +} + +function saveSeasonIgnore(seasonNumber, ignored) { + $.ajax({ + type: "POST", + url: saveSeasonIgnoreUrl, + data: jQuery.param({ seriesId: seriesId, seasonNumber: seasonNumber, ignored: ignored }), + error: function (req, status, error) { + alert("Sorry! We could save the ignore settings for Series: " + seriesId + ", Season: " + seasonNumber + " at this time. " + error); + } + }); +} + +function saveEpisodeIgnore(episodeId, ignored) { + $.ajax({ + type: "POST", + url: saveEpisodeIgnoreUrl, + data: jQuery.param({ episodeId: episodeId, ignored: ignored }), + error: function (req, status, error) { + alert("Sorry! We could save the ignore settings for Episode: " + episodeId + " at this time. " + error); + } + }); } \ No newline at end of file diff --git a/NzbDrone.Web/Views/Series/Details.cshtml b/NzbDrone.Web/Views/Series/Details.cshtml index 21d1ae8aa..2a4a44ddc 100644 --- a/NzbDrone.Web/Views/Series/Details.cshtml +++ b/NzbDrone.Web/Views/Series/Details.cshtml @@ -159,7 +159,7 @@ }); } - + seriesId = @Model.SeriesId; }