mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-17 15:02:34 +02:00
LINQ for paging missing episodes
This commit is contained in:
parent
a414a4663e
commit
d37c8c26c2
@ -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 @@ public virtual int GetRowCount()
|
||||
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 @@ public static IQuery CreateRowCountSelectQuery(TableCollection tables, IDataMapp
|
||||
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 @@ public static IQuery CreatePagingSelectQuery(TableCollection tables, IDataMapper
|
||||
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 @@ public virtual SortBuilder<T> AndWhere(string whereClause)
|
||||
|
||||
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 @@ public virtual SortBuilder<T> OrderBy(string orderByClause)
|
||||
|
||||
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 @@ public virtual string BuildQuery(bool useAltName)
|
||||
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 @@ public SortColumn(Expression<Func<T, object>> sortExpression, SortDirection dire
|
||||
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 @@ private MemberExpression GetMemberExpression(Expression exp)
|
||||
|
||||
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 @@ public static void InitializeAutomapper()
|
||||
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 @@ private Response GetHistory()
|
||||
// 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 @@ private Response GetMissingEpisodes()
|
||||
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 @@ public static void Map()
|
||||
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 @@ public QualityModel GetBestQualityInHistory(int episodeId)
|
||||
|
||||
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 @@ public List<Episode> GetEpisodeByFileId(int fileId)
|
||||
|
||||
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' }),
|
||||
|
Loading…
Reference in New Issue
Block a user