diff --git a/NzbDrone.Core.Test/JobTests/SeasonSearchJobTest.cs b/NzbDrone.Core.Test/JobTests/SeasonSearchJobTest.cs index ff8775278..bb5eae2e1 100644 --- a/NzbDrone.Core.Test/JobTests/SeasonSearchJobTest.cs +++ b/NzbDrone.Core.Test/JobTests/SeasonSearchJobTest.cs @@ -63,7 +63,7 @@ namespace NzbDrone.Core.Test.JobTests Mocker.GetMock() .Setup(c => c.PartialSeasonSearch(notification, 1, 1)) - .Returns(resultItems.ToList()); + .Returns(episodes.Select(e => e.EpisodeNumber).ToList()); //Act Mocker.Resolve().Start(notification, 1, 1); @@ -96,7 +96,7 @@ namespace NzbDrone.Core.Test.JobTests Mocker.GetMock() .Setup(c => c.PartialSeasonSearch(notification, 1, 1)) - .Returns(new List{ new SearchResultItem{ Success = true }}); + .Returns(new List()); //Act Mocker.Resolve().Start(notification, 1, 1); @@ -130,7 +130,7 @@ namespace NzbDrone.Core.Test.JobTests Mocker.GetMock() .Setup(c => c.PartialSeasonSearch(notification, 1, 1)) - .Returns(new List { new SearchResultItem { Success = false, SearchError = ReportRejectionType.Size} }); + .Returns(new List()); //Act diff --git a/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/ProcessSearchResultsFixture.cs b/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/ProcessSearchResultsFixture.cs index 72a6544ca..40c6022e4 100644 --- a/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/ProcessSearchResultsFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/SearchProviderTests/ProcessSearchResultsFixture.cs @@ -11,6 +11,7 @@ using NzbDrone.Core.Providers; using NzbDrone.Core.Providers.DecisionEngine; using NzbDrone.Core.Repository; using NzbDrone.Core.Repository.Quality; +using NzbDrone.Core.Repository.Search; using NzbDrone.Core.Test.Framework; namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests @@ -105,7 +106,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests .Returns(ReportRejectionType.None); //Act - var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1, 1); + var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchResult(), _matchingSeries, 1, 1); //Assert result.Should().HaveCount(parseResults.Count); @@ -138,7 +139,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests .Setup(s => s.IsSatisfiedBy(It.IsAny())).Returns(ReportRejectionType.None); //Act - var result = Mocker.Resolve().ProcessSearchResults(MockNotification, parseResults, _matchingSeries, 1, 1); + var result = Mocker.Resolve().ProcessSearchResults(MockNotification, parseResults, new SearchResult(), _matchingSeries, 1, 1); //Assert result.Should().HaveCount(parseResults.Count); @@ -163,7 +164,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests WithQualityNotNeeded(); //Act - var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1, 1); + var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchResult(), _matchingSeries, 1, 1); //Assert result.Should().HaveCount(parseResults.Count); @@ -187,7 +188,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests WithNullSeries(); //Act - var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1, 1); + var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchResult(), _matchingSeries, 1, 1); //Assert result.Should().HaveCount(parseResults.Count); @@ -209,7 +210,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests WithMisMatchedSeries(); //Act - var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1, 1); + var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchResult(), _matchingSeries, 1, 1); //Assert result.Should().HaveCount(parseResults.Count); @@ -231,7 +232,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests WithMatchingSeries(); //Act - var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1, 1); + var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchResult(), _matchingSeries, 1, 1); //Assert result.Should().HaveCount(parseResults.Count); @@ -253,7 +254,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests WithMatchingSeries(); //Act - var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1, 1); + var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchResult(), _matchingSeries, 1, 1); //Assert result.Should().HaveCount(parseResults.Count); @@ -280,7 +281,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests WithSuccessfulDownload(); //Act - var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1); + var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchResult(), _matchingSeries, 1); //Assert result.Should().HaveCount(parseResults.Count); @@ -314,7 +315,7 @@ namespace NzbDrone.Core.Test.ProviderTests.SearchProviderTests .Returns(true); //Act - var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, _matchingSeries, 1); + var result = Mocker.Resolve().ProcessSearchResults(new ProgressNotification("Test"), parseResults, new SearchResult(), _matchingSeries, 1); //Assert result.Should().HaveCount(parseResults.Count); diff --git a/NzbDrone.Core/Datastore/Migrations/Migration20120420.cs b/NzbDrone.Core/Datastore/Migrations/Migration20120420.cs index 62eae990f..688b3deaf 100644 --- a/NzbDrone.Core/Datastore/Migrations/Migration20120420.cs +++ b/NzbDrone.Core/Datastore/Migrations/Migration20120420.cs @@ -27,7 +27,12 @@ namespace NzbDrone.Core.Datastore.Migrations new Column("NzbUrl", DbType.String, ColumnProperty.NotNull), new Column("NzbInfoUrl", DbType.String, ColumnProperty.Null), new Column("Success", DbType.Boolean, ColumnProperty.NotNull), - new Column("SearchError", DbType.Int32, ColumnProperty.NotNull) + new Column("SearchError", DbType.Int32, ColumnProperty.NotNull), + new Column("Quality", DbType.Int32, ColumnProperty.NotNull), + new Column("Proper", DbType.Boolean, ColumnProperty.NotNull), + new Column("Age", DbType.Int32, ColumnProperty.NotNull), + new Column("Language", DbType.Int32, ColumnProperty.NotNull), + new Column("Size", DbType.Int64, ColumnProperty.NotNull), }); } } diff --git a/NzbDrone.Core/Fluent.cs b/NzbDrone.Core/Fluent.cs index f27ec5b76..a66ccbe20 100644 --- a/NzbDrone.Core/Fluent.cs +++ b/NzbDrone.Core/Fluent.cs @@ -87,5 +87,60 @@ namespace NzbDrone.Core return s.Substring(0, i); } + public static string AddSpacesToEnum(this Enum enumValue) + { + var text = enumValue.ToString(); + + if (string.IsNullOrWhiteSpace(text)) + return ""; + var newText = new StringBuilder(text.Length * 2); + newText.Append(text[0]); + for (int i = 1; i < text.Length; i++) + { + if (char.IsUpper(text[i]) && text[i - 1] != ' ') + newText.Append(' '); + newText.Append(text[i]); + } + return newText.ToString(); + } + + private const Decimal ONE_KILOBYTE = 1024M; + private const Decimal ONE_MEGABYTE = ONE_KILOBYTE * 1024M; + private const Decimal ONE_GIGABYTE = ONE_MEGABYTE * 1024M; + + public static string ToBestFileSize(this long bytes, int precision = 0) + { + if (bytes == 0) + return "0B"; + + decimal size = Convert.ToDecimal(bytes); + + string suffix; + + if (size > ONE_GIGABYTE) + { + size /= ONE_GIGABYTE; + suffix = "GB"; + } + + else if (size > ONE_MEGABYTE) + { + size /= ONE_MEGABYTE; + suffix = "MB"; + } + + else if (size > ONE_KILOBYTE) + { + size /= ONE_KILOBYTE; + suffix = "KB"; + } + + else + { + suffix = " B"; + } + + return String.Format("{0:N" + precision + "} {1}", size, suffix); + } } } diff --git a/NzbDrone.Core/Helpers/FileSizeFormatHelper.cs b/NzbDrone.Core/Helpers/FileSizeFormatHelper.cs deleted file mode 100644 index 515543fc8..000000000 --- a/NzbDrone.Core/Helpers/FileSizeFormatHelper.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; - -namespace NzbDrone.Core.Helpers -{ - public static class FileSizeFormatHelper - { - private const Decimal OneKiloByte = 1024M; - private const Decimal OneMegaByte = OneKiloByte * 1024M; - private const Decimal OneGigaByte = OneMegaByte * 1024M; - - public static string Format(long bytes, int precision = 0) - { - if (bytes == 0) - return "0B"; - - decimal size = Convert.ToDecimal(bytes); - - string suffix; - - if (size > OneGigaByte) - { - size /= OneGigaByte; - suffix = "GB"; - } - - else if (size > OneMegaByte) - { - size /= OneMegaByte; - suffix = "MB"; - } - - else if (size > OneKiloByte) - { - size /= OneKiloByte; - suffix = "KB"; - } - - else - { - suffix = " B"; - } - - return String.Format("{0:N" + precision + "}{1}", size, suffix); - } - } -} diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 4a65fae54..bf01b1298 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -240,7 +240,6 @@ - diff --git a/NzbDrone.Core/Providers/SearchProvider.cs b/NzbDrone.Core/Providers/SearchProvider.cs index fd51c6c1d..1537657e7 100644 --- a/NzbDrone.Core/Providers/SearchProvider.cs +++ b/NzbDrone.Core/Providers/SearchProvider.cs @@ -91,12 +91,13 @@ namespace NzbDrone.Core.Providers e => e.EpisodeNumbers = episodeNumbers.ToList() ); - searchResult.SearchResultItems = ProcessSearchResults(notification, reports, series, seasonNumber); + searchResult.SearchResultItems = ProcessSearchResults(notification, reports, searchResult, series, seasonNumber); + _searchResultProvider.Add(searchResult); - return (searchResult.SearchResultItems.Select(s => s.Success).Count() == episodeNumbers.Count); + return (searchResult.Successes.Count == episodeNumbers.Count); } - public virtual List PartialSeasonSearch(ProgressNotification notification, int seriesId, int seasonNumber) + public virtual List PartialSeasonSearch(ProgressNotification notification, int seriesId, int seasonNumber) { var searchResult = new SearchResult { @@ -110,12 +111,12 @@ namespace NzbDrone.Core.Providers if (series == null) { Logger.Error("Unable to find an series {0} in database", seriesId); - return new List(); + return new List(); } //Return empty list if the series is a daily series (we only support individual episode searching if (series.IsDaily) - return new List(); + return new List(); notification.CurrentMessage = String.Format("Searching for {0} Season {1}", series.Title, seasonNumber); var episodes = _episodeProvider.GetEpisodesBySeason(seriesId, seasonNumber); @@ -123,13 +124,13 @@ namespace NzbDrone.Core.Providers Logger.Debug("Finished searching all indexers. Total {0}", reports.Count); if (reports.Count == 0) - return new List(); + return new List(); notification.CurrentMessage = "Processing search results"; - searchResult.SearchResultItems = ProcessSearchResults(notification, reports, series, seasonNumber); + searchResult.SearchResultItems = ProcessSearchResults(notification, reports, searchResult, series, seasonNumber); _searchResultProvider.Add(searchResult); - return searchResult.SearchResultItems; + return searchResult.Successes; } public virtual bool EpisodeSearch(ProgressNotification notification, int episodeId) @@ -182,7 +183,7 @@ namespace NzbDrone.Core.Providers else { searchResult.EpisodeId = episodeId; - searchResult.SearchResultItems = ProcessSearchResults(notification, reports, episode.Series, episode.SeasonNumber, episode.EpisodeNumber); + searchResult.SearchResultItems = ProcessSearchResults(notification, reports, searchResult, episode.Series, episode.SeasonNumber, episode.EpisodeNumber); _searchResultProvider.Add(searchResult); if (searchResult.SearchResultItems.Any(r => r.Success)) @@ -256,7 +257,7 @@ namespace NzbDrone.Core.Providers return reports; } - public List ProcessSearchResults(ProgressNotification notification, IEnumerable reports, Series series, int seasonNumber, int? episodeNumber = null) + public List ProcessSearchResults(ProgressNotification notification, IEnumerable reports, SearchResult searchResult, Series series, int seasonNumber, int? episodeNumber = null) { var successes = new List(); var items = new List(); @@ -271,7 +272,12 @@ namespace NzbDrone.Core.Providers { ReportTitle = episodeParseResult.OriginalString, NzbUrl = episodeParseResult.NzbUrl, - Indexer = episodeParseResult.Indexer + Indexer = episodeParseResult.Indexer, + Quality = episodeParseResult.Quality.QualityType, + Proper = episodeParseResult.Quality.Proper, + Size = episodeParseResult.Size, + Age = episodeParseResult.Age, + Language = episodeParseResult.Language }; items.Add(item); @@ -360,7 +366,12 @@ namespace NzbDrone.Core.Providers { ReportTitle = episodeParseResult.OriginalString, NzbUrl = episodeParseResult.NzbUrl, - Indexer = episodeParseResult.Indexer + Indexer = episodeParseResult.Indexer, + Quality = episodeParseResult.Quality.QualityType, + Proper = episodeParseResult.Quality.Proper, + Size = episodeParseResult.Size, + Age = episodeParseResult.Age, + Language = episodeParseResult.Language }; items.Add(item); @@ -414,6 +425,7 @@ namespace NzbDrone.Core.Providers { Logger.ErrorException("Unable to add report to download queue." + episodeParseResult, e); notification.CurrentMessage = String.Format("Unable to add report to download queue. {0}", episodeParseResult); + item.SearchError = ReportRejectionType.DownloadClientFailure; } } } diff --git a/NzbDrone.Core/Providers/SearchResultProvider.cs b/NzbDrone.Core/Providers/SearchResultProvider.cs index cba3dc697..f01b9ffdb 100644 --- a/NzbDrone.Core/Providers/SearchResultProvider.cs +++ b/NzbDrone.Core/Providers/SearchResultProvider.cs @@ -13,12 +13,17 @@ namespace NzbDrone.Core.Providers public class SearchResultProvider { private readonly IDatabase _database; + private readonly SeriesProvider _seriesProvider; + private readonly DownloadProvider _downloadProvider; private static readonly Logger logger = LogManager.GetCurrentClassLogger(); [Inject] - public SearchResultProvider(IDatabase database) + public SearchResultProvider(IDatabase database, SeriesProvider seriesProvider, + DownloadProvider downloadProvider) { _database = database; + _seriesProvider = seriesProvider; + _downloadProvider = downloadProvider; } public SearchResultProvider() @@ -54,7 +59,7 @@ namespace NzbDrone.Core.Providers Episodes.EpisodeNumber, Episodes.SeasonNumber, Episodes.Title as EpisodeTitle, Episodes.AirDate, Count(SearchResultItems.Id) as TotalItems, - SUM(CASE WHEN SearchResultItems.Success = 1 THEN 1 ELSE 0 END) as Successes + SUM(CASE WHEN SearchResultItems.Success = 1 THEN 1 ELSE 0 END) as SuccessfulCount FROM SearchResults INNER JOIN Series ON Series.SeriesId = SearchResults.SeriesId @@ -73,10 +78,36 @@ namespace NzbDrone.Core.Providers public virtual SearchResult GetSearchResult(int id) { - var result = _database.Single(id); + var sql = @"SELECT SearchResults.Id, SearchResults.SeriesId, SearchResults.SeasonNumber, + SearchResults.EpisodeId, SearchResults.SearchTime, + Series.Title as SeriesTitle, Series.IsDaily, + Episodes.EpisodeNumber, Episodes.SeasonNumber, Episodes.Title as EpisodeTitle, + Episodes.AirDate + FROM SearchResults + INNER JOIN Series + ON Series.SeriesId = SearchResults.SeriesId + LEFT JOIN Episodes + ON Episodes.EpisodeId = SearchResults.EpisodeId + WHERE SearchResults.Id = @0"; + + var result = _database.Single(sql, id); result.SearchResultItems = _database.Fetch("WHERE SearchResultId = @0", id); return result; } + + public virtual void ForceDownload(int itemId) + { + var item = _database.Single(itemId); + var searchResult = _database.Single(item.SearchResultId); + var series = _seriesProvider.GetSeries(searchResult.SeriesId); + + var parseResult = Parser.ParseTitle(item.ReportTitle); + parseResult.NzbUrl = item.NzbUrl; + parseResult.Series = series; + parseResult.Indexer = item.Indexer; + + _downloadProvider.DownloadReport(parseResult); + } } } diff --git a/NzbDrone.Core/Repository/Search/SearchResult.cs b/NzbDrone.Core/Repository/Search/SearchResult.cs index 50ef04550..1d5069940 100644 --- a/NzbDrone.Core/Repository/Search/SearchResult.cs +++ b/NzbDrone.Core/Repository/Search/SearchResult.cs @@ -21,6 +21,9 @@ namespace NzbDrone.Core.Repository.Search [ResultColumn] public List SearchResultItems { get; set; } + [Ignore] + public List Successes { get; set; } + [ResultColumn] public string SeriesTitle { get; set; } @@ -40,6 +43,6 @@ namespace NzbDrone.Core.Repository.Search public int TotalItems { get; set; } [ResultColumn] - public int Successes { get; set; } + public int SuccessfulCount { get; set; } } } \ No newline at end of file diff --git a/NzbDrone.Core/Repository/Search/SearchResultItem.cs b/NzbDrone.Core/Repository/Search/SearchResultItem.cs index 51b744e59..091783319 100644 --- a/NzbDrone.Core/Repository/Search/SearchResultItem.cs +++ b/NzbDrone.Core/Repository/Search/SearchResultItem.cs @@ -19,5 +19,15 @@ namespace NzbDrone.Core.Repository.Search public string NzbInfoUrl { get; set; } public bool Success { get; set; } public ReportRejectionType SearchError { get; set; } + public QualityTypes Quality { get; set; } + public bool Proper { get; set; } + public int Age { get; set; } + public LanguageType Language { get; set; } + public long Size { get; set; } + + public override string ToString() + { + return String.Format("{0} - {1} - {2}", ReportTitle, Quality, SearchError); + } } } \ No newline at end of file diff --git a/NzbDrone.Web/Controllers/LogController.cs b/NzbDrone.Web/Controllers/LogController.cs index 5db86794c..6df8bd2ad 100644 --- a/NzbDrone.Web/Controllers/LogController.cs +++ b/NzbDrone.Web/Controllers/LogController.cs @@ -4,11 +4,10 @@ using System.Linq; using System.Linq.Dynamic; using System.Text; using System.Web.Mvc; +using DataTables.Mvc.Core; using DataTables.Mvc.Core.Models; using NzbDrone.Common; using NzbDrone.Core.Instrumentation; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Repository.Search; using NzbDrone.Web.Models; namespace NzbDrone.Web.Controllers @@ -18,15 +17,13 @@ namespace NzbDrone.Web.Controllers private readonly LogProvider _logProvider; private readonly EnvironmentProvider _environmentProvider; private readonly DiskProvider _diskProvider; - private readonly SearchResultProvider _searchResultProvider; public LogController(LogProvider logProvider, EnvironmentProvider environmentProvider, - DiskProvider diskProvider, SearchResultProvider searchResultProvider) + DiskProvider diskProvider) { _logProvider = logProvider; _environmentProvider = environmentProvider; _diskProvider = diskProvider; - _searchResultProvider = searchResultProvider; } public ActionResult Index() @@ -55,28 +52,6 @@ namespace NzbDrone.Web.Controllers return JsonNotificationResult.Info("Logs Cleared"); } - public ActionResult SearchResults() - { - var results = _searchResultProvider.AllSearchResults(); - - var model = results.Select(s => new SearchResultsModel - { - Id = s.Id, - SearchTime = s.SearchTime.ToString(), - DisplayName = GetDisplayName(s), - ReportCount = s.TotalItems, - Successful = s.Successes > 0 - }); - - return View(model); - } - - public ActionResult SearchDetails(int searchId) - { - var model = _searchResultProvider.GetSearchResult(searchId); - return View(model); - } - public ActionResult AjaxBinding(DataTablesParams dataTablesParams) { var logs = _logProvider.GetAllLogs(); @@ -129,24 +104,5 @@ namespace NzbDrone.Web.Controllers }, JsonRequestBehavior.AllowGet); } - - public string GetDisplayName(SearchResult searchResult) - { - if (!searchResult.EpisodeNumber.HasValue) - { - return String.Format("{0} - Season {1}", searchResult.SeriesTitle, searchResult.SeasonNumber); - } - - string episodeString; - - if (searchResult.IsDaily) - episodeString = searchResult.AirDate.ToShortDateString().Replace('/', '-'); - - else - episodeString = String.Format("S{0:00}E{1:00}", searchResult.SeasonNumber, - searchResult.EpisodeNumber); - - return String.Format("{0} - {1} - {2}", searchResult.SeriesTitle, episodeString, searchResult.EpisodeTitle); - } } } \ No newline at end of file diff --git a/NzbDrone.Web/Controllers/SearchResultController.cs b/NzbDrone.Web/Controllers/SearchResultController.cs new file mode 100644 index 000000000..ea5867095 --- /dev/null +++ b/NzbDrone.Web/Controllers/SearchResultController.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using NzbDrone.Core; +using NzbDrone.Core.Providers; +using NzbDrone.Core.Repository.Search; +using NzbDrone.Web.Models; + +namespace NzbDrone.Web.Controllers +{ + public class SearchResultController : Controller + { + private readonly SearchResultProvider _searchResultProvider; + + public SearchResultController(SearchResultProvider searchResultProvider) + { + _searchResultProvider = searchResultProvider; + } + + public ActionResult Index() + { + var results = _searchResultProvider.AllSearchResults(); + + var model = results.Select(s => new SearchResultsModel + { + Id = s.Id, + SearchTime = s.SearchTime.ToString(), + DisplayName = GetDisplayName(s), + ReportCount = s.TotalItems, + Successful = s.SuccessfulCount > 0 + }); + + return View(model); + } + + public ActionResult Details(int searchId) + { + var searchResult = _searchResultProvider.GetSearchResult(searchId); + var model = new SearchDetailsModel + { + Id = searchResult.Id, + DisplayName = GetDisplayName(searchResult), + SearchResultItems = + searchResult.SearchResultItems.Select(s => new SearchItemModel + { + Id = s.Id, + ReportTitle = s.ReportTitle, + Indexer = s.Indexer, + NzbUrl = s.NzbUrl, + NzbInfoUrl = s.NzbInfoUrl, + Success = s.Success, + SearchError = s.SearchError.AddSpacesToEnum().Replace("None", "Grabbed"), + Quality = s.Quality.ToString(), + QualityInt = (int)s.Quality, + Proper = s.Proper, + Age = s.Age, + Size = s.Size.ToBestFileSize(1), + Language = s.Language.ToString() + }).ToList() + }; + + return View(model); + } + + public JsonResult ForceDownload(int id) + { + _searchResultProvider.ForceDownload(id); + + return new JsonResult { Data = "ok", JsonRequestBehavior = JsonRequestBehavior.AllowGet }; + } + + public string GetDisplayName(SearchResult searchResult) + { + if (!searchResult.EpisodeNumber.HasValue) + { + return String.Format("{0} - Season {1}", searchResult.SeriesTitle, searchResult.SeasonNumber); + } + + string episodeString; + + if (searchResult.IsDaily) + episodeString = searchResult.AirDate.ToShortDateString().Replace('/', '-'); + + else + episodeString = String.Format("S{0:00}E{1:00}", searchResult.SeasonNumber, + searchResult.EpisodeNumber); + + return String.Format("{0} - {1} - {2}", searchResult.SeriesTitle, episodeString, searchResult.EpisodeTitle); + } + } +} diff --git a/NzbDrone.Web/Controllers/SystemController.cs b/NzbDrone.Web/Controllers/SystemController.cs index a8c7406da..da688d12e 100644 --- a/NzbDrone.Web/Controllers/SystemController.cs +++ b/NzbDrone.Web/Controllers/SystemController.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Web.Mvc; using System.Web.Script.Serialization; using NzbDrone.Common; +using NzbDrone.Core; using NzbDrone.Core.Helpers; using NzbDrone.Core.Jobs; using NzbDrone.Core.Providers; @@ -129,7 +130,7 @@ namespace NzbDrone.Web.Controllers foreach (var fileInfo in files) { fileResult += String.Format("
{0}
{1}
", fileInfo.Name, - FileSizeFormatHelper.Format(fileInfo.Length, 1)); + fileInfo.Length.ToBestFileSize(1)); } model.Files = fileResult; diff --git a/NzbDrone.Web/Models/SearchDetailsModel.cs b/NzbDrone.Web/Models/SearchDetailsModel.cs new file mode 100644 index 000000000..ce198cf59 --- /dev/null +++ b/NzbDrone.Web/Models/SearchDetailsModel.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using NzbDrone.Core.Repository.Search; + +namespace NzbDrone.Web.Models +{ + public class SearchDetailsModel + { + public int Id { get; set; } + public string DisplayName { get; set; } + public List SearchResultItems { get; set; } + } +} \ No newline at end of file diff --git a/NzbDrone.Web/Models/SearchItemModel.cs b/NzbDrone.Web/Models/SearchItemModel.cs new file mode 100644 index 000000000..7e9821a18 --- /dev/null +++ b/NzbDrone.Web/Models/SearchItemModel.cs @@ -0,0 +1,23 @@ +using NzbDrone.Core.Model; +using NzbDrone.Core.Repository.Quality; + +namespace NzbDrone.Web.Models +{ + public class SearchItemModel + { + public int Id { get; set; } + public string ReportTitle { get; set; } + public string Indexer { get; set; } + public string NzbUrl { get; set; } + public string NzbInfoUrl { get; set; } + public bool Success { get; set; } + public string SearchError { get; set; } + public string Quality { get; set; } + public int QualityInt { get; set; } + public bool Proper { get; set; } + public int Age { get; set; } + public string Language { get; set; } + public string Size { get; set; } + public string Details { get; set; } + } +} \ No newline at end of file diff --git a/NzbDrone.Web/NzbDrone.Web.csproj b/NzbDrone.Web/NzbDrone.Web.csproj index 778b6edcf..16dab8a16 100644 --- a/NzbDrone.Web/NzbDrone.Web.csproj +++ b/NzbDrone.Web/NzbDrone.Web.csproj @@ -52,7 +52,8 @@ - ..\packages\DataTables.Mvc.0.1.0.54\lib\DataTables.Mvc.Core.dll + ..\packages\DataTables.Mvc.0.1.0.67\lib\DataTables.Mvc.Core.dll + True ..\packages\DynamicQuery.1.0\lib\35\Dynamic.dll @@ -141,6 +142,7 @@ + @@ -234,9 +236,11 @@ + + @@ -521,7 +525,10 @@ - + + + + 10.0 diff --git a/NzbDrone.Web/Views/SearchResult/Details.cshtml b/NzbDrone.Web/Views/SearchResult/Details.cshtml new file mode 100644 index 000000000..701b07804 --- /dev/null +++ b/NzbDrone.Web/Views/SearchResult/Details.cshtml @@ -0,0 +1,45 @@ +@using DataTables.Mvc.Core +@using DataTables.Mvc.Core.Enum +@model NzbDrone.Web.Models.SearchDetailsModel + +@{ + ViewBag.Title = "Search Details"; +} + +

@Model.DisplayName

+ +@Html.GridHtml("searchDetailsGrid") + +@section Scripts +{ + @(Html.GridScriptFor(m => m.SearchResultItems, "#searchDetailsGrid") + .PageLength(20) + .ChangePageLength(false) + .AddColumn(new Column().Image("/Content/Images/Indexers/{Indexer}.png", new { alt = "{Indexer}", title = "{Indexer}" }, "{Indexer}").Sortable(false).Title("").Width("20px")) + .AddColumn(new Column().DataProperty("ReportTitle").Title("Report Title")) + .AddColumn(new Column().DataProperty("Success").Title("Successful").Width("120px")) + .AddColumn(new Column().DisplayAndSort("Quality", "QualityInt").Title("Quality").Width("80px")) + .AddColumn(new Column().DataProperty("SearchError").Title("Error")) + .AddColumn(new Column().DataProperty("return actionColumn(source, type, val);", true)) + .AddColumn(new Column().DataProperty("Details").RenderFunction("return getDetails(row, val);").Visible(false)) + .AddSorting(3, SortDirection.Desc)) + + +} diff --git a/NzbDrone.Web/Views/Log/SearchResults.cshtml b/NzbDrone.Web/Views/SearchResult/Index.cshtml similarity index 84% rename from NzbDrone.Web/Views/Log/SearchResults.cshtml rename to NzbDrone.Web/Views/SearchResult/Index.cshtml index 4c1b9057c..d28fc1b6f 100644 --- a/NzbDrone.Web/Views/Log/SearchResults.cshtml +++ b/NzbDrone.Web/Views/SearchResult/Index.cshtml @@ -10,10 +10,10 @@ @section Scripts { @( - Html.GridScriptForModel("#searchResultsGrid") + Html.GridScriptForModel("#searchResultsGrid") .PageLength(20) .ChangePageLength(false) - .AddColumn(new Column().DataProperty("DisplayName").Link("SearchDetails?searchId={Id}", "{DisplayName}").Title("Name")) + .AddColumn(new Column().DataProperty("DisplayName").Link("SearchResult/Details?searchId={Id}", "{DisplayName}", null).Title("Name")) .AddColumn(new Column().DataProperty("SearchTime").Title("Time").Width("170px")) .AddColumn(new Column().DataProperty("ReportCount").Title("Reports Found").Width("140px")) .AddColumn(new Column().DataProperty("Successful").Title("Successful").Width("110px")) diff --git a/NzbDrone.Web/packages.config b/NzbDrone.Web/packages.config index 1427f9d68..c6a1961b2 100644 --- a/NzbDrone.Web/packages.config +++ b/NzbDrone.Web/packages.config @@ -1,6 +1,6 @@  - + diff --git a/packages/DataTables.Mvc.0.1.0.54/DataTables.Mvc.0.1.0.54.nupkg b/packages/DataTables.Mvc.0.1.0.54/DataTables.Mvc.0.1.0.54.nupkg deleted file mode 100644 index 28848589e..000000000 Binary files a/packages/DataTables.Mvc.0.1.0.54/DataTables.Mvc.0.1.0.54.nupkg and /dev/null differ diff --git a/packages/DataTables.Mvc.0.1.0.54/lib/DataTables.Mvc.Core.dll b/packages/DataTables.Mvc.0.1.0.54/lib/DataTables.Mvc.Core.dll deleted file mode 100644 index c6457bd9b..000000000 Binary files a/packages/DataTables.Mvc.0.1.0.54/lib/DataTables.Mvc.Core.dll and /dev/null differ diff --git a/packages/DataTables.Mvc.0.1.0.67/Content/App_Start/DataTablesMvc.cs.pp b/packages/DataTables.Mvc.0.1.0.67/Content/App_Start/DataTablesMvc.cs.pp new file mode 100644 index 000000000..abaaa76f4 --- /dev/null +++ b/packages/DataTables.Mvc.0.1.0.67/Content/App_Start/DataTablesMvc.cs.pp @@ -0,0 +1,17 @@ +using DataTables.Mvc.Core.Helpers; +using DataTables.Mvc.Core.Models; +using System.Web.Mvc; + +[assembly: WebActivator.PreApplicationStartMethod(typeof($rootnamespace$.App_Start.DataTablesModelBinderActivator), "Start")] + +namespace $rootnamespace$.App_Start +{ + public static class DataTablesModelBinderActivator + { + public static void Start() + { + if (!ModelBinders.Binders.ContainsKey(typeof(DataTablesParams))) + ModelBinders.Binders.Add(typeof(DataTablesParams), new DataTablesModelBinder()); + } + } +} \ No newline at end of file diff --git a/packages/DataTables.Mvc.0.1.0.67/DataTables.Mvc.0.1.0.67.nupkg b/packages/DataTables.Mvc.0.1.0.67/DataTables.Mvc.0.1.0.67.nupkg new file mode 100644 index 000000000..a3bc6861c Binary files /dev/null and b/packages/DataTables.Mvc.0.1.0.67/DataTables.Mvc.0.1.0.67.nupkg differ diff --git a/packages/DataTables.Mvc.0.1.0.67/lib/DataTables.Mvc.Core.dll b/packages/DataTables.Mvc.0.1.0.67/lib/DataTables.Mvc.Core.dll new file mode 100644 index 000000000..a18c8bf2c Binary files /dev/null and b/packages/DataTables.Mvc.0.1.0.67/lib/DataTables.Mvc.Core.dll differ diff --git a/packages/DataTables.Mvc.0.1.0.67/tools/install.ps1 b/packages/DataTables.Mvc.0.1.0.67/tools/install.ps1 new file mode 100644 index 000000000..7e1f5357f --- /dev/null +++ b/packages/DataTables.Mvc.0.1.0.67/tools/install.ps1 @@ -0,0 +1,5 @@ +param($installPath, $toolsPath, $package, $project) + +$path = [System.IO.Path] +$appstart = $path::Combine($path::GetDirectoryName($project.FileName), "App_Start\DataTablesMvc.cs") +$DTE.ItemOperations.OpenFile($appstart) \ No newline at end of file