diff --git a/NzbDrone.Api/Series/SeriesModule.cs b/NzbDrone.Api/Series/SeriesModule.cs index 5e0314a52..a16fc1000 100644 --- a/NzbDrone.Api/Series/SeriesModule.cs +++ b/NzbDrone.Api/Series/SeriesModule.cs @@ -31,8 +31,20 @@ namespace NzbDrone.Api.Series private Response AllSeries() { var series = _seriesService.GetAllSeries().ToList(); + var seriesStats = _seriesService.SeriesStatistics(); var seriesModels = Mapper.Map, List>(series); + foreach (var s in seriesModels) + { + var stats = seriesStats.SingleOrDefault(ss => ss.SeriesId == s.Id); + if (stats == null) continue; + + s.EpisodeCount = stats.EpisodeCount; + s.EpisodeFileCount = stats.EpisodeFileCount; + s.NumberOfSeasons = stats.NumberOfSeasons; + s.NextAiring = stats.NextAiring; + } + return seriesModels.AsResponse(); } diff --git a/NzbDrone.Api/Series/SeriesResource.cs b/NzbDrone.Api/Series/SeriesResource.cs index 478bc9a39..158d12f40 100644 --- a/NzbDrone.Api/Series/SeriesResource.cs +++ b/NzbDrone.Api/Series/SeriesResource.cs @@ -21,12 +21,12 @@ namespace NzbDrone.Api.Series public String Overview { get; set; } public Int32 Episodes { get; set; } public Boolean HasBanner { get; set; } - public DateTime NextAiring { get; set; } + public DateTime? NextAiring { get; set; } public String Details { get; set; } public String Network { get; set; } public String AirTime { get; set; } public String Language { get; set; } - public Int32 SeasonCount { get; set; } + public Int32 NumberOfSeasons { get; set; } public Int32 UtcOffset { get; set; } public List Images { get; set; } diff --git a/NzbDrone.Core/Datastore/TableMapping.cs b/NzbDrone.Core/Datastore/TableMapping.cs index e0893b627..a133e67f3 100644 --- a/NzbDrone.Core/Datastore/TableMapping.cs +++ b/NzbDrone.Core/Datastore/TableMapping.cs @@ -56,6 +56,10 @@ namespace NzbDrone.Core.Datastore Mapper.Entity().RegisterModel("QualitySizes"); Mapper.Entity().RegisterModel("Logs"); + + Mapper.Entity() + .Columns + .AutoMapPropertiesWhere(MappingExtensions.IsMappableProperty); } diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 1bb52baf0..0949857c7 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -386,6 +386,7 @@ + diff --git a/NzbDrone.Core/Tv/SeriesRepository.cs b/NzbDrone.Core/Tv/SeriesRepository.cs index 02190c5c0..023365510 100644 --- a/NzbDrone.Core/Tv/SeriesRepository.cs +++ b/NzbDrone.Core/Tv/SeriesRepository.cs @@ -13,13 +13,17 @@ namespace NzbDrone.Core.Tv Series FindByTvdbId(int tvdbId); void SetSeriesType(int seriesId, SeriesTypes seriesTypes); void SetTvRageId(int seriesId, int tvRageId); + List SeriesStatistics(); } public class SeriesRepository : BasicRepository, ISeriesRepository { + private readonly IDatabase _database; + public SeriesRepository(IDatabase database) : base(database) { + _database = database; } public bool SeriesPathExists(string path) @@ -51,5 +55,22 @@ namespace NzbDrone.Core.Tv { SetFields(new Series { Id = seriesId, TvRageId = tvRageId }, s => s.TvRageId); } + + public List SeriesStatistics() + { + _database.DataMapper.AddParameter("currentDate", DateTime.UtcNow); + + var queryText = @"SELECT + SeriesId, + SUM(CASE WHEN Airdate <= @currentDate THEN 1 ELSE 0 END) AS EpisodeCount, + SUM(CASE WHEN EpisodeFileId > 0 AND AirDate <= @currentDate THEN 1 ELSE 0 END) as EpisodeFileCount, + MAX(SeasonNumber) as NumberOfSeasons, + MIN(CASE WHEN AirDate < @currentDate THEN NULL ELSE AirDate END) as NextAiring + FROM Episodes + WHERE Ignored = 0 + GROUP BY SeriesId"; + + return _database.DataMapper.Query(queryText); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/Tv/SeriesService.cs b/NzbDrone.Core/Tv/SeriesService.cs index 34b2e669c..a5cd611d8 100644 --- a/NzbDrone.Core/Tv/SeriesService.cs +++ b/NzbDrone.Core/Tv/SeriesService.cs @@ -33,6 +33,7 @@ namespace NzbDrone.Core.Tv void UpdateSeries(Series series); bool SeriesPathExists(string folder); List GetSeriesInList(IEnumerable seriesIds); + List SeriesStatistics(); } public class SeriesService : ISeriesService, IHandleAsync @@ -58,7 +59,6 @@ namespace NzbDrone.Core.Tv _logger = logger; } - public bool IsMonitored(int id) { return _seriesRepository.Get(id).Monitored; @@ -179,6 +179,11 @@ namespace NzbDrone.Core.Tv return _seriesRepository.Get(seriesIds).ToList(); } + public List SeriesStatistics() + { + return _seriesRepository.SeriesStatistics(); + } + public void HandleAsync(SeriesAddedEvent message) { UpdateSeriesInfo(message.Series.Id); diff --git a/NzbDrone.Core/Tv/SeriesStatistics.cs b/NzbDrone.Core/Tv/SeriesStatistics.cs new file mode 100644 index 000000000..5e9bfc228 --- /dev/null +++ b/NzbDrone.Core/Tv/SeriesStatistics.cs @@ -0,0 +1,13 @@ +using System; + +namespace NzbDrone.Core.Tv +{ + public class SeriesStatistics + { + public int SeriesId { get; set; } + public int NumberOfSeasons { get; set; } + public DateTime? NextAiring { get; set; } + public int EpisodeFileCount { get; set; } + public int EpisodeCount { get; set; } + } +} diff --git a/UI/Series/Index/SeriesItemTemplate.html b/UI/Series/Index/SeriesItemTemplate.html index 06453cd34..39944eab4 100644 --- a/UI/Series/Index/SeriesItemTemplate.html +++ b/UI/Series/Index/SeriesItemTemplate.html @@ -1,6 +1,6 @@ {{{formatStatus status monitored}}} {{title}} - +