diff --git a/frontend/src/Components/Form/MonitorAlbumsSelectInput.js b/frontend/src/Components/Form/MonitorAlbumsSelectInput.js index 14075f9f9..71f39a146 100644 --- a/frontend/src/Components/Form/MonitorAlbumsSelectInput.js +++ b/frontend/src/Components/Form/MonitorAlbumsSelectInput.js @@ -4,11 +4,11 @@ import SelectInput from './SelectInput'; const monitorOptions = [ { key: 'all', value: 'All Albums' }, - // { key: 'future', value: 'Future Albums' }, - // { key: 'missing', value: 'Missing Albums' }, - // { key: 'existing', value: 'Existing Albums' }, - // { key: 'first', value: 'Only First Album' }, - // { key: 'latest', value: 'Only Latest Album' }, + { key: 'future', value: 'Future Albums' }, + { key: 'missing', value: 'Missing Albums' }, + { key: 'existing', value: 'Existing Albums' }, + { key: 'first', value: 'Only First Album' }, + { key: 'latest', value: 'Only Latest Album' }, { key: 'none', value: 'None' } ]; diff --git a/frontend/src/Utilities/Artist/getMonitoringOptions.js b/frontend/src/Utilities/Artist/getMonitoringOptions.js index 62588b8b8..e6a7f28fd 100644 --- a/frontend/src/Utilities/Artist/getMonitoringOptions.js +++ b/frontend/src/Utilities/Artist/getMonitoringOptions.js @@ -2,26 +2,32 @@ import _ from 'lodash'; function getMonitoringOptions(monitor) { const monitoringOptions = { - ignoreAlbumsWithFiles: false, - ignoreAlbumsWithoutFiles: false, + selectedOption: 0, monitored: true }; switch (monitor) { case 'future': - monitoringOptions.ignoreAlbumsWithFiles = true; - monitoringOptions.ignoreAlbumsWithoutFiles = true; + monitoringOptions.selectedOption = 1; break; case 'missing': - monitoringOptions.ignoreAlbumsWithFiles = true; + monitoringOptions.selectedOption = 2; break; case 'existing': - monitoringOptions.ignoreAlbumsWithoutFiles = true; + monitoringOptions.selectedOption = 3; + break; + case 'first': + monitoringOptions.selectedOption = 5; + break; + case 'latest': + monitoringOptions.selectedOption = 4; break; case 'none': monitoringOptions.monitored = false; + monitoringOptions.selectedOption = 6; break; default: + monitoringOptions.selectedOption = 0; break; } diff --git a/src/NzbDrone.Core.Test/MusicTests/AlbumMonitoredServiceTests/AlbumMonitoredServiceFixture.cs b/src/NzbDrone.Core.Test/MusicTests/AlbumMonitoredServiceTests/AlbumMonitoredServiceFixture.cs index c8bc171d9..077aa0e9f 100644 --- a/src/NzbDrone.Core.Test/MusicTests/AlbumMonitoredServiceTests/AlbumMonitoredServiceFixture.cs +++ b/src/NzbDrone.Core.Test/MusicTests/AlbumMonitoredServiceTests/AlbumMonitoredServiceFixture.cs @@ -42,6 +42,10 @@ namespace NzbDrone.Core.Test.MusicTests.AlbumMonitoredServiceTests .Setup(s => s.GetAlbumsByArtist(It.IsAny())) .Returns(_albums); + Mocker.GetMock() + .Setup(s => s.GetArtistAlbumsWithFiles(It.IsAny())) + .Returns(new List()); + Mocker.GetMock() .Setup(s => s.GetTracksByAlbum(It.IsAny())) .Returns(new List()); @@ -83,13 +87,11 @@ namespace NzbDrone.Core.Test.MusicTests.AlbumMonitoredServiceTests } [Test] - [Ignore("Not Implemented Yet")] public void should_be_able_to_monitor_new_albums_only() { var monitoringOptions = new MonitoringOptions { - IgnoreAlbumsWithFiles = true, - IgnoreAlbumsWithoutFiles = true + SelectedOption = MonitoringOption.Future }; Subject.SetAlbumMonitoredStatus(_artist, monitoringOptions); diff --git a/src/NzbDrone.Core/ImportLists/ImportListSyncService.cs b/src/NzbDrone.Core/ImportLists/ImportListSyncService.cs index 3cdbc15b2..db1c7d545 100644 --- a/src/NzbDrone.Core/ImportLists/ImportListSyncService.cs +++ b/src/NzbDrone.Core/ImportLists/ImportListSyncService.cs @@ -106,7 +106,7 @@ namespace NzbDrone.Core.ImportLists LanguageProfileId = importList.LanguageProfileId, MetadataProfileId = importList.MetadataProfileId, AlbumFolder = true, - AddOptions = new AddArtistOptions{SearchForMissingAlbums = true, Monitored = importList.ShouldMonitor } + AddOptions = new AddArtistOptions{SearchForMissingAlbums = true, Monitored = importList.ShouldMonitor, SelectedOption = 0} }); } diff --git a/src/NzbDrone.Core/Music/AlbumMonitoredService.cs b/src/NzbDrone.Core/Music/AlbumMonitoredService.cs index bcf146dd6..1eb0355d9 100644 --- a/src/NzbDrone.Core/Music/AlbumMonitoredService.cs +++ b/src/NzbDrone.Core/Music/AlbumMonitoredService.cs @@ -1,8 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; +using System.Net.Sockets; using NLog; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Datastore; namespace NzbDrone.Core.Music { @@ -34,8 +37,13 @@ namespace NzbDrone.Core.Music var albums = _albumService.GetAlbumsByArtist(artist.Id); + var albumsWithFiles = _albumService.GetArtistAlbumsWithFiles(artist); + + var albumsWithoutFiles = albums.Where(c => !albumsWithFiles.Select(e => e.Id).Contains(c.Id) && c.ReleaseDate <= DateTime.UtcNow).ToList(); + var monitoredAlbums = monitoringOptions.AlbumsToMonitor; + // If specific albums are passed use those instead of the monitoring options. if (monitoredAlbums.Any()) { ToggleAlbumsMonitoredState( @@ -45,11 +53,45 @@ namespace NzbDrone.Core.Music } else { - ToggleAlbumsMonitoredState(albums, monitoringOptions.Monitored); + switch (monitoringOptions.SelectedOption) + { + case MonitoringOption.All: + ToggleAlbumsMonitoredState(albums, true); + break; + case MonitoringOption.Future: + _logger.Debug("Unmonitoring Albums with Files"); + ToggleAlbumsMonitoredState(albums.Where(e => albumsWithFiles.Select(c => c.Id).Contains(e.Id)), false); + _logger.Debug("Unmonitoring Albums without Files"); + ToggleAlbumsMonitoredState(albums.Where(e => albumsWithoutFiles.Select(c => c.Id).Contains(e.Id)), false); + break; + case MonitoringOption.None: + ToggleAlbumsMonitoredState(albums, false); + break; + case MonitoringOption.Missing: + _logger.Debug("Unmonitoring Albums with Files"); + ToggleAlbumsMonitoredState(albums.Where(e => albumsWithFiles.Select(c => c.Id).Contains(e.Id)), false); + _logger.Debug("Monitoring Albums without Files"); + ToggleAlbumsMonitoredState(albums.Where(e => albumsWithoutFiles.Select(c => c.Id).Contains(e.Id)), true); + break; + case MonitoringOption.Existing: + _logger.Debug("Monitoring Albums with Files"); + ToggleAlbumsMonitoredState(albums.Where(e => albumsWithFiles.Select(c => c.Id).Contains(e.Id)), true); + _logger.Debug("Unmonitoring Albums without Files"); + ToggleAlbumsMonitoredState(albums.Where(e => albumsWithoutFiles.Select(c => c.Id).Contains(e.Id)), false); + break; + case MonitoringOption.Latest: + ToggleAlbumsMonitoredState(albums, false); + ToggleAlbumsMonitoredState(albums.OrderByDescending(e=>e.ReleaseDate).Take(1),true); + break; + case MonitoringOption.First: + ToggleAlbumsMonitoredState(albums, false); + ToggleAlbumsMonitoredState(albums.OrderBy(e => e.ReleaseDate).Take(1), true); + break; + default: + throw new ArgumentOutOfRangeException(); + } } - //TODO Add Other Options for Future/Exisitng/Missing Once we have a good way to check for Album Related Files. - _albumService.UpdateAlbums(albums); } diff --git a/src/NzbDrone.Core/Music/AlbumRepository.cs b/src/NzbDrone.Core/Music/AlbumRepository.cs index 935a74615..2ebeb2df2 100644 --- a/src/NzbDrone.Core/Music/AlbumRepository.cs +++ b/src/NzbDrone.Core/Music/AlbumRepository.cs @@ -25,6 +25,7 @@ namespace NzbDrone.Core.Music void SetMonitoredFlat(Album album, bool monitored); void SetMonitored(IEnumerable ids, bool monitored); Album FindAlbumByRelease(string releaseId); + List GetArtistAlbumsWithFiles(Artist artist); } public class AlbumRepository : BasicRepository, IAlbumRepository @@ -307,5 +308,19 @@ namespace NzbDrone.Core.Music { return Query.FirstOrDefault(e => e.Releases.Any(r => r.Id == releaseId)); } + + public List GetArtistAlbumsWithFiles(Artist artist) + { + string query = string.Format("SELECT Albums.* FROM (SELECT Tracks.AlbumId, COUNT(*) AS TotalTrackCount," + "" + + "SUM(CASE WHEN TrackFileId > 0 THEN 1 ELSE 0 END) AS AvailableTrackCount FROM Tracks GROUP BY Tracks.ArtistId, Tracks.AlbumId) as Tracks" + + " LEFT OUTER JOIN Albums ON Tracks.AlbumId == Albums.Id" + + " LEFT OUTER JOIN Artists ON Albums.ArtistId == Artists.Id" + + " WHERE Tracks.AvailableTrackCount > 0" + + " AND Albums.ArtistId=" + artist.Id + + " GROUP BY Tracks.AlbumId"); + + return Query.QueryText(query); + + } } } diff --git a/src/NzbDrone.Core/Music/AlbumService.cs b/src/NzbDrone.Core/Music/AlbumService.cs index bd1d9bfc1..8b4774338 100644 --- a/src/NzbDrone.Core/Music/AlbumService.cs +++ b/src/NzbDrone.Core/Music/AlbumService.cs @@ -32,6 +32,7 @@ namespace NzbDrone.Core.Music void DeleteMany(List albums); void RemoveAddOptions(Album album); Album FindAlbumByRelease(string releaseId); + List GetArtistAlbumsWithFiles(Artist artist); } public class AlbumService : IAlbumService, @@ -142,6 +143,11 @@ namespace NzbDrone.Core.Music return albums; } + public List GetArtistAlbumsWithFiles(Artist artist) + { + return _albumRepository.GetArtistAlbumsWithFiles(artist); + } + public void InsertMany(List albums) { _albumRepository.InsertMany(albums); diff --git a/src/NzbDrone.Core/Music/MonitoringOptions.cs b/src/NzbDrone.Core/Music/MonitoringOptions.cs index aa824975d..802a0e809 100644 --- a/src/NzbDrone.Core/Music/MonitoringOptions.cs +++ b/src/NzbDrone.Core/Music/MonitoringOptions.cs @@ -9,10 +9,20 @@ namespace NzbDrone.Core.Music { AlbumsToMonitor = new List(); } - - public bool IgnoreAlbumsWithFiles { get; set; } - public bool IgnoreAlbumsWithoutFiles { get; set; } + + public MonitoringOption SelectedOption { get; set; } public List AlbumsToMonitor { get; set; } public bool Monitored { get; set; } } + + public enum MonitoringOption + { + All = 0, + Future = 1, + Missing = 2, + Existing = 3, + Latest = 4, + First = 5, + None = 6 + } } diff --git a/src/NzbDrone.Core/Music/TrackMonitoredService.cs b/src/NzbDrone.Core/Music/TrackMonitoredService.cs deleted file mode 100644 index 720e00865..000000000 --- a/src/NzbDrone.Core/Music/TrackMonitoredService.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NLog; -using NzbDrone.Common.Extensions; - -namespace NzbDrone.Core.Music -{ - public interface ITrackMonitoredService - { - void SetTrackMonitoredStatus(Artist album, MonitoringOptions monitoringOptions); - } - - public class TrackMonitoredService : ITrackMonitoredService - { - private readonly IArtistService _albumService; - private readonly ITrackService _trackService; - private readonly Logger _logger; - - public TrackMonitoredService(IArtistService albumService, ITrackService trackService, Logger logger) - { - _albumService = albumService; - _trackService = trackService; - _logger = logger; - } - - public void SetTrackMonitoredStatus(Artist album, MonitoringOptions monitoringOptions) - { - if (monitoringOptions != null) - { - _logger.Debug("[{0}] Setting track monitored status.", album.Name); - - var tracks = _trackService.GetTracksByArtist(album.Id); - - if (monitoringOptions.IgnoreAlbumsWithFiles) - { - _logger.Debug("Ignoring Tracks with Files"); - ToggleTracksMonitoredState(tracks.Where(e => e.HasFile), false); - } - - else - { - _logger.Debug("Monitoring Tracks with Files"); - ToggleTracksMonitoredState(tracks.Where(e => e.HasFile), true); - } - - if (monitoringOptions.IgnoreAlbumsWithoutFiles) - { - _logger.Debug("Ignoring Tracks without Files"); - ToggleTracksMonitoredState(tracks.Where(e => !e.HasFile), false); - } - - else - { - _logger.Debug("Monitoring Episodes without Files"); - ToggleTracksMonitoredState(tracks.Where(e => !e.HasFile), true); - } - - _trackService.UpdateTracks(tracks); - } - - _albumService.UpdateArtist(album); - } - - private void ToggleTracksMonitoredState(IEnumerable tracks, bool monitored) - { - foreach (var track in tracks) - { - track.Monitored = monitored; - } - } - } -} diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 21b2a05f0..e28c31bb3 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -829,7 +829,6 @@ -