You've already forked Sonarr
							
							
				mirror of
				https://github.com/Sonarr/Sonarr.git
				synced 2025-10-31 00:07:55 +02:00 
			
		
		
		
	LINQ for paging missing episodes
This commit is contained in:
		| @@ -72,6 +72,8 @@ | ||||
|     <Compile Include="IDataMapper.cs" /> | ||||
|     <Compile Include="LazyLoaded.cs" /> | ||||
|     <Compile Include="Mapping\FluentMappings.cs" /> | ||||
|     <Compile Include="QGen\SqliteRowCountQueryDecorator.cs" /> | ||||
|     <Compile Include="QGen\SqlitePagingQueryDecorator.cs" /> | ||||
|     <Compile Include="UnitOfWork.cs" /> | ||||
|     <Compile Include="UnitOfWorkSharedContext.cs" /> | ||||
|     <Compile Include="Mapping\ColumnMapBuilder.cs" /> | ||||
|   | ||||
| @@ -241,7 +241,7 @@ namespace Marr.Data.QGen | ||||
|             string queryText = query.Generate(); | ||||
|  | ||||
|             _db.SqlMode = SqlModes.Text; | ||||
|             int count = (int)_db.ExecuteScalar(queryText); | ||||
|             int count = Convert.ToInt32(_db.ExecuteScalar(queryText)); | ||||
|  | ||||
|             _db.SqlMode = previousSqlMode; | ||||
|             return count; | ||||
|   | ||||
| @@ -56,6 +56,9 @@ namespace Marr.Data.QGen | ||||
|                 case DB_SqlCeClient: | ||||
|                     return new RowCountQueryDecorator(innerQuery); | ||||
|  | ||||
|                 case DB_SQLiteClient: | ||||
|                     return new SqliteRowCountQueryDecorator(innerQuery); | ||||
|  | ||||
|                 default: | ||||
|                     throw new NotImplementedException("Row count has not yet been implemented for this provider."); | ||||
|             } | ||||
| @@ -74,6 +77,9 @@ namespace Marr.Data.QGen | ||||
|                 case DB_SqlCeClient: | ||||
|                     return new PagingQueryDecorator(innerQuery, skip, take); | ||||
|  | ||||
|                 case DB_SQLiteClient: | ||||
|                     return new SqlitePagingQueryDecorator(innerQuery, skip, take); | ||||
|  | ||||
|                 default: | ||||
|                     throw new NotImplementedException("Paging has not yet been implemented for this provider."); | ||||
|             } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.ComponentModel; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Linq.Expressions; | ||||
| @@ -77,13 +78,13 @@ namespace Marr.Data.QGen | ||||
|  | ||||
|         internal SortBuilder<T> Order(Type declaringType, string propertyName) | ||||
|         { | ||||
|             _sortExpressions.Add(new SortColumn<T>(declaringType, propertyName, SortDirection.Asc)); | ||||
|             _sortExpressions.Add(new SortColumn<T>(declaringType, propertyName, ListSortDirection.Ascending)); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         internal SortBuilder<T> OrderByDescending(Type declaringType, string propertyName) | ||||
|         { | ||||
|             _sortExpressions.Add(new SortColumn<T>(declaringType, propertyName, SortDirection.Desc)); | ||||
|             _sortExpressions.Add(new SortColumn<T>(declaringType, propertyName, ListSortDirection.Descending)); | ||||
|             return this; | ||||
|         } | ||||
|          | ||||
| @@ -103,25 +104,37 @@ namespace Marr.Data.QGen | ||||
|  | ||||
|         public virtual SortBuilder<T> OrderBy(Expression<Func<T, object>> sortExpression) | ||||
|         { | ||||
|             _sortExpressions.Add(new SortColumn<T>(sortExpression, SortDirection.Asc)); | ||||
|             _sortExpressions.Add(new SortColumn<T>(sortExpression, ListSortDirection.Ascending)); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public virtual SortBuilder<T> OrderBy(Expression<Func<T, object>> sortExpression, ListSortDirection sortDirection) | ||||
|         { | ||||
|             _sortExpressions.Add(new SortColumn<T>(sortExpression, sortDirection)); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public virtual SortBuilder<T> OrderByDescending(Expression<Func<T, object>> sortExpression) | ||||
|         { | ||||
|             _sortExpressions.Add(new SortColumn<T>(sortExpression, SortDirection.Desc)); | ||||
|             _sortExpressions.Add(new SortColumn<T>(sortExpression, ListSortDirection.Descending)); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public virtual SortBuilder<T> ThenBy(Expression<Func<T, object>> sortExpression) | ||||
|         { | ||||
|             _sortExpressions.Add(new SortColumn<T>(sortExpression, SortDirection.Asc)); | ||||
|             _sortExpressions.Add(new SortColumn<T>(sortExpression, ListSortDirection.Ascending)); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public virtual SortBuilder<T> ThenBy(Expression<Func<T, object>> sortExpression, ListSortDirection sortDirection) | ||||
|         { | ||||
|             _sortExpressions.Add(new SortColumn<T>(sortExpression, sortDirection)); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public virtual SortBuilder<T> ThenByDescending(Expression<Func<T, object>> sortExpression) | ||||
|         { | ||||
|             _sortExpressions.Add(new SortColumn<T>(sortExpression, SortDirection.Desc)); | ||||
|             _sortExpressions.Add(new SortColumn<T>(sortExpression, ListSortDirection.Descending)); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
| @@ -198,7 +211,7 @@ namespace Marr.Data.QGen | ||||
|                 string columnName = DataHelper.GetColumnName(sort.DeclaringType, sort.PropertyName, useAltName); | ||||
|                 sb.Append(_dialect.CreateToken(string.Format("{0}.{1}", table.Alias, columnName))); | ||||
|  | ||||
|                 if (sort.Direction == SortDirection.Desc) | ||||
|                 if (sort.Direction == ListSortDirection.Descending) | ||||
|                     sb.Append(" DESC"); | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.ComponentModel; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Linq.Expressions; | ||||
| @@ -9,7 +10,24 @@ namespace Marr.Data.QGen | ||||
| { | ||||
|     public class SortColumn<T> | ||||
|     { | ||||
|         [Obsolete("Use ListSortDirection instead")] | ||||
|         public SortColumn(Expression<Func<T, object>> sortExpression, SortDirection direction) | ||||
|         { | ||||
|             MemberExpression me = GetMemberExpression(sortExpression.Body); | ||||
|             DeclaringType = me.Expression.Type; | ||||
|             PropertyName = me.Member.Name; | ||||
|             Direction = GetSortDirection(direction); | ||||
|         } | ||||
|  | ||||
|         [Obsolete("Use ListSortDirection instead")] | ||||
|         public SortColumn(Type declaringType, string propertyName, SortDirection direction) | ||||
|         { | ||||
|             DeclaringType = declaringType; | ||||
|             PropertyName = propertyName; | ||||
|             Direction = GetSortDirection(direction); | ||||
|         } | ||||
|  | ||||
|         public SortColumn(Expression<Func<T, object>> sortExpression, ListSortDirection direction) | ||||
|         { | ||||
|             MemberExpression me = GetMemberExpression(sortExpression.Body); | ||||
|             DeclaringType = me.Expression.Type; | ||||
| @@ -17,14 +35,14 @@ namespace Marr.Data.QGen | ||||
|             Direction = direction; | ||||
|         } | ||||
|  | ||||
|         public SortColumn(Type declaringType, string propertyName, SortDirection direction) | ||||
|         public SortColumn(Type declaringType, string propertyName, ListSortDirection direction) | ||||
|         { | ||||
|             DeclaringType = declaringType; | ||||
|             PropertyName = propertyName; | ||||
|             Direction = direction; | ||||
|         } | ||||
|  | ||||
|         public SortDirection Direction { get; private set; } | ||||
|         public ListSortDirection Direction { get; private set; } | ||||
|         public Type DeclaringType { get; private set; } | ||||
|         public string PropertyName { get; private set; } | ||||
|  | ||||
| @@ -40,6 +58,13 @@ namespace Marr.Data.QGen | ||||
|  | ||||
|             return me; | ||||
|         } | ||||
|  | ||||
|         private ListSortDirection GetSortDirection(SortDirection direction) | ||||
|         { | ||||
|             if (direction == SortDirection.Desc) return ListSortDirection.Descending; | ||||
|                  | ||||
|             return ListSortDirection.Ascending; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     public enum SortDirection | ||||
|   | ||||
							
								
								
									
										90
									
								
								Marr.Data/QGen/SqlitePagingQueryDecorator.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								Marr.Data/QGen/SqlitePagingQueryDecorator.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using Marr.Data.Mapping; | ||||
| using Marr.Data.QGen.Dialects; | ||||
|  | ||||
| namespace Marr.Data.QGen | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Decorates the SelectQuery by wrapping it in a paging query. | ||||
|     /// </summary> | ||||
|     public class SqlitePagingQueryDecorator : IQuery | ||||
|     { | ||||
|         private SelectQuery _innerQuery; | ||||
|         private int _skip; | ||||
|         private int _take; | ||||
|  | ||||
|         public SqlitePagingQueryDecorator(SelectQuery innerQuery, int skip, int take) | ||||
|         { | ||||
|             if (string.IsNullOrEmpty(innerQuery.OrderBy.ToString())) | ||||
|             { | ||||
|                 throw new DataMappingException("A paged query must specify an order by clause."); | ||||
|             } | ||||
|  | ||||
|             _innerQuery = innerQuery; | ||||
|             _skip = skip; | ||||
|             _take = take; | ||||
|         } | ||||
|  | ||||
|         public string Generate() | ||||
|         { | ||||
|             StringBuilder sql = new StringBuilder(); | ||||
|  | ||||
|             _innerQuery.BuildSelectClause(sql); | ||||
|             _innerQuery.BuildFromClause(sql); | ||||
|             _innerQuery.BuildJoinClauses(sql); | ||||
|             _innerQuery.BuildWhereClause(sql); | ||||
|             _innerQuery.BuildOrderClause(sql); | ||||
|             sql.AppendLine(String.Format(" LIMIT {0},{1}", _skip, _take)); | ||||
|  | ||||
|             return sql.ToString(); | ||||
|         } | ||||
|  | ||||
|         public void BuildSelectClause(StringBuilder sql) | ||||
|         { | ||||
|             List<string> appended = new List<string>(); | ||||
|  | ||||
|             sql.Append("SELECT "); | ||||
|  | ||||
|             int startIndex = sql.Length; | ||||
|  | ||||
|             // COLUMNS | ||||
|             foreach (Table join in _innerQuery.Tables) | ||||
|             { | ||||
|                 for (int i = 0; i < join.Columns.Count; i++) | ||||
|                 { | ||||
|                     var c = join.Columns[i]; | ||||
|  | ||||
|                     if (sql.Length > startIndex && sql[sql.Length - 1] != ',') | ||||
|                         sql.Append(","); | ||||
|  | ||||
|                     if (join is View) | ||||
|                     { | ||||
|                         string token = _innerQuery.Dialect.CreateToken(string.Concat(join.Alias, ".", _innerQuery.NameOrAltName(c.ColumnInfo))); | ||||
|                         if (appended.Contains(token)) | ||||
|                             continue; | ||||
|  | ||||
|                         sql.Append(token); | ||||
|                         appended.Add(token); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         string token = string.Concat(join.Alias, ".", c.ColumnInfo.Name); | ||||
|                         if (appended.Contains(token)) | ||||
|                             continue; | ||||
|  | ||||
|                         sql.Append(_innerQuery.Dialect.CreateToken(token)); | ||||
|  | ||||
|                         if (_innerQuery.UseAltName && c.ColumnInfo.AltName != null && c.ColumnInfo.AltName != c.ColumnInfo.Name) | ||||
|                         { | ||||
|                             string altName = c.ColumnInfo.AltName; | ||||
|                             sql.AppendFormat(" AS {0}", altName); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										34
									
								
								Marr.Data/QGen/SqliteRowCountQueryDecorator.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								Marr.Data/QGen/SqliteRowCountQueryDecorator.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
|  | ||||
| namespace Marr.Data.QGen | ||||
| { | ||||
|     public class SqliteRowCountQueryDecorator : IQuery | ||||
|     { | ||||
|         private SelectQuery _innerQuery; | ||||
|  | ||||
|         public SqliteRowCountQueryDecorator(SelectQuery innerQuery) | ||||
|         { | ||||
|             _innerQuery = innerQuery; | ||||
|         } | ||||
|          | ||||
|         public string Generate() | ||||
|         { | ||||
|             StringBuilder sql = new StringBuilder(); | ||||
|  | ||||
|             BuildSelectCountClause(sql); | ||||
|             _innerQuery.BuildFromClause(sql); | ||||
|             _innerQuery.BuildJoinClauses(sql); | ||||
|             _innerQuery.BuildWhereClause(sql); | ||||
|  | ||||
|             return sql.ToString(); | ||||
|         } | ||||
|  | ||||
|         private void BuildSelectCountClause(StringBuilder sql) | ||||
|         { | ||||
|             sql.AppendLine("SELECT COUNT(*)"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -45,7 +45,9 @@ namespace NzbDrone.Api | ||||
|             Mapper.CreateMap<PagingSpec<Episode>, PagingResource<EpisodeResource>>(); | ||||
|  | ||||
|             //History | ||||
|             Mapper.CreateMap<Core.History.History, HistoryResource>(); | ||||
|             Mapper.CreateMap<Core.History.History, HistoryResource>() | ||||
|                 .ForMember(dest => dest.Episode, opt => opt.Ignore()) | ||||
|                 .ForMember(dest => dest.Series, opt => opt.Ignore()); | ||||
|             Mapper.CreateMap<PagingSpec<Core.History.History>, PagingResource<HistoryResource>>(); | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -69,6 +69,24 @@ namespace NzbDrone.Api.History | ||||
| //                                                           Series = series, | ||||
|                                                            Indexer = "nzbs.org", | ||||
|                                                            Quality = new QualityModel(Quality.HDTV720p) | ||||
|                                                        }, | ||||
|                                                     new Core.History.History | ||||
|                                                         { | ||||
|                                                             Id = 2, | ||||
|                                                             Date = DateTime.UtcNow.AddDays(-1), | ||||
|         //                                                           Episode = episode, | ||||
|         //                                                           Series = series, | ||||
|                                                             Indexer = "nzbs.org", | ||||
|                                                             Quality = new QualityModel(Quality.SDTV, true) | ||||
|                                                         }, | ||||
|                                                     new Core.History.History | ||||
|                                                        { | ||||
|                                                            Id = 3, | ||||
|                                                            Date = DateTime.UtcNow.AddDays(-5), | ||||
| //                                                           Episode = episode, | ||||
| //                                                           Series = series, | ||||
|                                                            Indexer = "nzbs.org", | ||||
|                                                            Quality = new QualityModel(Quality.WEBDL1080p) | ||||
|                                                        } | ||||
|                                                } | ||||
|                              }; | ||||
|   | ||||
| @@ -36,8 +36,8 @@ namespace NzbDrone.Api.Missing | ||||
|             if (page == 0) page = 1; | ||||
|  | ||||
|             var sortKey = PrimitiveExtensions.ToNullSafeString(Request.Query.SortKey) | ||||
|                                                    .Equals("SeriesTitle", StringComparison.InvariantCultureIgnoreCase) | ||||
|                                                    ? "SeriesTitle" | ||||
|                                                    .Equals("Series.Title", StringComparison.InvariantCultureIgnoreCase) | ||||
|                                                    ? "Series.Title" | ||||
|                                                    : "AirDate"; | ||||
|  | ||||
|             var sortDirection = PrimitiveExtensions.ToNullSafeString(Request.Query.SortDir) | ||||
|   | ||||
| @@ -0,0 +1,25 @@ | ||||
| using System.ComponentModel; | ||||
| using FluentAssertions; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Core.Datastore; | ||||
| using NzbDrone.Core.Tv; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.Datastore.PagingSpecExtenstionsTests | ||||
| { | ||||
|     public class OrderByClauseFixture | ||||
|     { | ||||
|         [Test] | ||||
|         public void Test() | ||||
|         { | ||||
|             var pagingSpec = new PagingSpec<Episode> | ||||
|                 { | ||||
|                     Page = 1, | ||||
|                     PageSize = 10, | ||||
|                     SortDirection = ListSortDirection.Ascending, | ||||
|                     SortKey = "AirDate" | ||||
|                 }; | ||||
|  | ||||
|             pagingSpec.OrderByClause().Should().NotBeNullOrEmpty(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -120,6 +120,7 @@ | ||||
|     <Compile Include="Datastore\DatabaseRelationshipFixture.cs" /> | ||||
|     <Compile Include="Datastore\MappingExtentionFixture.cs" /> | ||||
|     <Compile Include="Datastore\ObjectDatabaseFixture.cs" /> | ||||
|     <Compile Include="Datastore\PagingSpecExtenstionsTests\OrderByClauseFixture.cs" /> | ||||
|     <Compile Include="Download\DownloadClientTests\BlackholeProviderFixture.cs" /> | ||||
|     <Compile Include="Download\DownloadClientTests\NzbgetProviderTests\DownloadNzbFixture.cs" /> | ||||
|     <Compile Include="Download\DownloadClientTests\NzbgetProviderTests\QueueFixture.cs" /> | ||||
|   | ||||
							
								
								
									
										41
									
								
								NzbDrone.Core/Datastore/PagingSpecExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								NzbDrone.Core/Datastore/PagingSpecExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.ComponentModel; | ||||
| using System.Linq; | ||||
| using System.Linq.Expressions; | ||||
| using System.Reflection; | ||||
| using System.Text; | ||||
|  | ||||
| namespace NzbDrone.Core.Datastore | ||||
| { | ||||
|     public static class PagingSpecExtensions | ||||
|     { | ||||
|         public static Expression<Func<TModel, object>> OrderByClause<TModel>(this PagingSpec<TModel> pagingSpec) | ||||
|         { | ||||
|             return CreateExpression<TModel>(pagingSpec.SortKey); | ||||
|         } | ||||
|  | ||||
|         public static int PagingOffset<TModel>(this PagingSpec<TModel> pagingSpec) | ||||
|         { | ||||
|             return (pagingSpec.Page - 1)*pagingSpec.PageSize; | ||||
|         } | ||||
|  | ||||
|         private static Expression<Func<TModel, object>> CreateExpression<TModel>(string propertyName) | ||||
|         { | ||||
|             Type type = typeof(TModel); | ||||
|             ParameterExpression parameterExpression = Expression.Parameter(type, "x"); | ||||
|             Expression expressionBody = parameterExpression; | ||||
|  | ||||
|             var splitPropertyName = propertyName.Split('.').ToList(); | ||||
|  | ||||
|             foreach (var property in splitPropertyName) | ||||
|             { | ||||
|                 expressionBody = Expression.Property(expressionBody, property); | ||||
|             } | ||||
|  | ||||
|             expressionBody = Expression.Convert(expressionBody, typeof(object)); | ||||
|             return Expression.Lambda<Func<TModel, object>>(expressionBody, parameterExpression); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|      | ||||
| @@ -67,10 +67,6 @@ namespace NzbDrone.Core.Datastore | ||||
|             Mapper.Entity<SeriesStatistics>().MapResultSet(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|         private static void RegisterMappers() | ||||
|         { | ||||
|             RegisterEmbeddedConverter(); | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Data; | ||||
| using System.Linq; | ||||
| using NzbDrone.Common.Messaging; | ||||
| @@ -39,5 +40,7 @@ namespace NzbDrone.Core.History | ||||
|  | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         //public List<History> GetPagedHistory()  | ||||
|     } | ||||
| } | ||||
| @@ -211,6 +211,7 @@ | ||||
|     <Compile Include="Datastore\ModelBase.cs" /> | ||||
|     <Compile Include="Datastore\BasicRepository.cs" /> | ||||
|     <Compile Include="Datastore\PagingSpec.cs" /> | ||||
|     <Compile Include="Datastore\PagingSpecExtensions.cs" /> | ||||
|     <Compile Include="Datastore\RelationshipExtensions.cs" /> | ||||
|     <Compile Include="Datastore\TableMapping.cs" /> | ||||
|     <Compile Include="DecisionEngine\DownloadDecision.cs" /> | ||||
|   | ||||
| @@ -2,7 +2,9 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.ComponentModel; | ||||
| using System.Data; | ||||
| using System.Diagnostics; | ||||
| using System.Linq; | ||||
| using FluentMigrator.Runner; | ||||
| using Marr.Data; | ||||
| using Marr.Data.QGen; | ||||
| using NzbDrone.Common.Messaging; | ||||
| @@ -65,40 +67,25 @@ namespace NzbDrone.Core.Tv | ||||
|  | ||||
|         public PagingSpec<Episode> EpisodesWithoutFiles(PagingSpec<Episode> pagingSpec, bool includeSpecials) | ||||
|         { | ||||
|             //TODO: Join in the series title so we can do sorting on it | ||||
|             if (!pagingSpec.SortKey.Equals("SeriesTitle", StringComparison.InvariantCultureIgnoreCase) && | ||||
|                 !pagingSpec.SortKey.Equals("AirDate", StringComparison.InvariantCultureIgnoreCase)) | ||||
|             { | ||||
|                 throw new ArgumentException("Invalid SortKey: " + pagingSpec.SortKey, "pagingSpec"); | ||||
|             } | ||||
|  | ||||
|             if (includeSpecials) | ||||
|             { | ||||
|                 throw new NotImplementedException("Including specials is not available"); | ||||
|             } | ||||
|  | ||||
|             var orderSql = String.Format("{0} {1}", pagingSpec.SortKey, | ||||
|                                          pagingSpec.SortDirection == ListSortDirection.Ascending ? "ASC" : "DESC"); | ||||
|  | ||||
|             var limitSql = String.Format("{0},{1}", (pagingSpec.Page - 1) * pagingSpec.PageSize, pagingSpec.PageSize); | ||||
|  | ||||
|              | ||||
|             //This causes an issue if done within the LINQ Query | ||||
|             var currentTime = DateTime.UtcNow; | ||||
|             _dataMapper.AddParameter("currentTime", currentTime); | ||||
|  | ||||
|             var sql = String.Format(@"SELECT Episodes.*, Series.Title as SeriesTitle | ||||
|                                       FROM Episodes | ||||
|                                       INNER JOIN Series | ||||
|                                       ON Episodes.SeriesId = Series.Id | ||||
|                                       WHERE EpisodeFileId = 0 | ||||
|                                       AND SeasonNumber > 0 | ||||
|                                       AND AirDate <= @currentTime | ||||
|                                       ORDER BY {0} | ||||
|                                       LIMIT {1}", | ||||
|                                       orderSql, limitSql | ||||
|                                    ); | ||||
|             pagingSpec.Records = Query.Join<Episode, Series>(JoinType.Inner, e => e.Series, (e, s) => e.SeriesId == s.Id) | ||||
|                              .Where(e => e.EpisodeFileId == 0) | ||||
|                              .AndWhere(e => e.SeasonNumber > 0) | ||||
|                              .AndWhere(e => e.AirDate <= currentTime) | ||||
|                              .OrderBy(pagingSpec.OrderByClause(), pagingSpec.SortDirection) | ||||
|                              .Skip(pagingSpec.PagingOffset()) | ||||
|                              .Take(pagingSpec.PageSize) | ||||
|                              .ToList(); | ||||
|  | ||||
|             pagingSpec.Records = _dataMapper.Query<Episode>(sql); | ||||
|             pagingSpec.TotalRecords = Query.Count(e => e.EpisodeFileId == 0 && e.SeasonNumber > 0 && e.AirDate <= currentTime); | ||||
|             //TODO: Use the same query for count and records | ||||
|             pagingSpec.TotalRecords = Query.Where(e => e.EpisodeFileId == 0 && e.SeasonNumber > 0 && e.AirDate <= currentTime).GetRowCount(); | ||||
|  | ||||
|             return pagingSpec; | ||||
|         } | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| <SolutionConfiguration> | ||||
|   <FileVersion>1</FileVersion> | ||||
|   <AutoEnableOnStartup>True</AutoEnableOnStartup> | ||||
|   <AutoEnableOnStartup>False</AutoEnableOnStartup> | ||||
|   <AllowParallelTestExecution>true</AllowParallelTestExecution> | ||||
|   <AllowTestsToRunInParallelWithThemselves>true</AllowTestsToRunInParallelWithThemselves> | ||||
|   <FrameworkUtilisationTypeForNUnit>UseDynamicAnalysis</FrameworkUtilisationTypeForNUnit> | ||||
|   <FrameworkUtilisationTypeForGallio>Disabled</FrameworkUtilisationTypeForGallio> | ||||
|   <FrameworkUtilisationTypeForMSpec>Disabled</FrameworkUtilisationTypeForMSpec> | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| "use strict"; | ||||
| define(['app', 'History/Model'], function () { | ||||
|     NzbDrone.Missing.Collection = Backbone.PageableCollection.extend({ | ||||
|     NzbDrone.History.Collection = Backbone.PageableCollection.extend({ | ||||
|         url       : NzbDrone.Constants.ApiRoot + '/history', | ||||
|         model     : NzbDrone.History.Model, | ||||
|  | ||||
|   | ||||
| @@ -1 +1,2 @@ | ||||
| <i class="icon-search x-search" title="Search"></i> | ||||
| <i class="icon-remove x-remove" title="Remove"></i> | ||||
| <i class="icon-repeat x-redownload" title="Re-Download"></i> | ||||
| @@ -1,2 +0,0 @@ | ||||
|  | ||||
| {{seasonNumber}}x{{paddedEpisodeNumber}} | ||||
| @@ -18,11 +18,18 @@ define([ | ||||
|             showTable: function () { | ||||
|  | ||||
|                 var columns = [ | ||||
|                     { | ||||
|                         name      : 'indexer', | ||||
|                         label     : '', | ||||
|                         editable  : false, | ||||
|                         cell      : Backgrid.TemplateBackedCell.extend({ template: 'History/IndexerTemplate' }), | ||||
|                         headerCell: 'nzbDrone' | ||||
|                     }, | ||||
|                     { | ||||
|                         name      : 'seriesTitle', | ||||
|                         label     : 'Series Title', | ||||
|                         editable  : false, | ||||
|                         cell      : Backgrid.TemplateBackedCell.extend({ template: 'History/SeriesTitleTemplate' }), | ||||
|                         cell      : Backgrid.TemplateBackedCell.extend({ template: 'Missing/SeriesTitleTemplate' }), | ||||
|                         headerCell: 'nzbDrone' | ||||
|                     }, | ||||
|                     { | ||||
| @@ -30,11 +37,11 @@ define([ | ||||
|                         label     : 'Episode', | ||||
|                         editable  : false, | ||||
|                         sortable  : false, | ||||
|                         cell      : Backgrid.TemplateBackedCell.extend({ template: 'History/EpisodeColumnTemplate' }), | ||||
|                         cell      : Backgrid.TemplateBackedCell.extend({ template: 'Missing/EpisodeColumnTemplate' }), | ||||
|                         headerCell: 'nzbDrone' | ||||
|                     }, | ||||
|                     { | ||||
|                         name      : 'title', | ||||
|                         name      : 'episode.title', | ||||
|                         label     : 'Episode Title', | ||||
|                         editable  : false, | ||||
|                         sortable  : false, | ||||
| @@ -42,8 +49,15 @@ define([ | ||||
|                         headerCell: 'nzbDrone' | ||||
|                     }, | ||||
|                     { | ||||
|                         name      : 'airDate', | ||||
|                         label     : 'Air Date', | ||||
|                         name      : 'quality', | ||||
|                         label     : 'Quality', | ||||
|                         editable  : false, | ||||
|                         cell      : Backgrid.TemplateBackedCell.extend({ template: 'History/QualityTemplate' }), | ||||
|                         headerCell: 'nzbDrone' | ||||
|                     }, | ||||
|                     { | ||||
|                         name      : 'date', | ||||
|                         label     : 'Grabbed', | ||||
|                         editable  : false, | ||||
|                         cell      : 'airDate', | ||||
|                         headerCell: 'nzbDrone' | ||||
|   | ||||
							
								
								
									
										1
									
								
								UI/History/IndexerTemplate.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								UI/History/IndexerTemplate.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| <img src="favicon.ico" alt="{{indexer}}"/> | ||||
							
								
								
									
										5
									
								
								UI/History/QualityTemplate.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								UI/History/QualityTemplate.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| {{quality.quality.name}} | ||||
|  | ||||
| {{#if quality.proper}} | ||||
|     [PROPER] | ||||
| {{/if}} | ||||
| @@ -1 +0,0 @@ | ||||
| <a href="series/details/{{series.titleSlug}}">{{series.title}}</a> | ||||
| @@ -20,7 +20,7 @@ define([ | ||||
|  | ||||
|                 var columns = [ | ||||
|                     { | ||||
|                         name      : 'seriesTitle', | ||||
|                         name      : 'series.Title', | ||||
|                         label     : 'Series Title', | ||||
|                         editable  : false, | ||||
|                         cell      : Backgrid.TemplateBackedCell.extend({ template: 'Missing/SeriesTitleTemplate' }), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user