diff --git a/NzbDrone.Core.Test/SeriesProviderTest.cs b/NzbDrone.Core.Test/SeriesProviderTest.cs index 15c1f8210..9d8d001fa 100644 --- a/NzbDrone.Core.Test/SeriesProviderTest.cs +++ b/NzbDrone.Core.Test/SeriesProviderTest.cs @@ -633,5 +633,51 @@ namespace NzbDrone.Core.Test series.Should().HaveCount(1); series[0].NextAiring.Should().Be(DateTime.Today.AddMonths(1)); } + + [Test] + public void SearchForSeries_should_return_results_that_start_with_query() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + var db = MockLib.GetEmptyDatabase(); + mocker.SetConstant(db); + + var fakeQuality = Builder.CreateNew().Build(); + var fakeSeries = Builder.CreateListOfSize(10) + .WhereAll() + .Have(e => e.QualityProfileId = fakeQuality.QualityProfileId) + .Build(); + + db.InsertMany(fakeSeries); + db.Insert(fakeQuality); + + //Act + var series = mocker.Resolve().SearchForSeries("Titl"); + + //Assert + series.Should().HaveCount(10); + } + + [Test] + public void SearchForSeries_should_not_return_results_that_do_not_start_with_query() + { + var mocker = new AutoMoqer(MockBehavior.Strict); + var db = MockLib.GetEmptyDatabase(); + mocker.SetConstant(db); + + var fakeQuality = Builder.CreateNew().Build(); + var fakeSeries = Builder.CreateListOfSize(10) + .WhereAll() + .Have(e => e.QualityProfileId = fakeQuality.QualityProfileId) + .Build(); + + db.InsertMany(fakeSeries); + db.Insert(fakeQuality); + + //Act + var series = mocker.Resolve().SearchForSeries("NotATitle"); + + //Assert + series.Should().HaveCount(0); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/SeriesProvider.cs b/NzbDrone.Core/Providers/SeriesProvider.cs index c87e4b91e..56aa435fa 100644 --- a/NzbDrone.Core/Providers/SeriesProvider.cs +++ b/NzbDrone.Core/Providers/SeriesProvider.cs @@ -186,6 +186,21 @@ namespace NzbDrone.Core.Providers return false; } + public virtual List SearchForSeries(string title) + { + var query = String.Format(@"SELECT * FROM Series + INNER JOIN QualityProfiles ON Series.QualityProfileId = QualityProfiles.QualityProfileId + WHERE Title LIKE '{0}%'", title); + +// var series = _database.Fetch(@"SELECT * FROM Series +// INNER JOIN QualityProfiles ON Series.QualityProfileId = QualityProfiles.QualityProfileId +// WHERE Title LIKE '@0%'", title); + + var series = _database.Fetch(query); + + return series; + } + /// /// Cleans up the AirsTime Component from TheTVDB since it can be garbage that comes in. /// diff --git a/NzbDrone.Web/Content/Slider.css b/NzbDrone.Web/Content/Slider.css new file mode 100644 index 000000000..aa76fce7b --- /dev/null +++ b/NzbDrone.Web/Content/Slider.css @@ -0,0 +1,67 @@ +.top-slider { + position: absolute; + opacity: 0.85; + width: 300px; +} + +.sliderButton { + border: 0; +} + +.sliderContent { + background-color:#333333; + text-align:center; + width: 100%; + color:#FFFFFF; + font-weight:bold; + margin: 0px; + display: none; + + @*Rounded Edges*@ + border:1px solid #444444; + -moz-border-radius-bottomright: 8px; + -webkit-border-bottom-right-radius: 8px; + -moz-border-radius-bottomleft: 8px; + -webkit-border-bottom-left-radius: 8px; +} + +.openCloseWrapper { + width: 100%; + text-align: center; + font-size:12px; + font-weight:bold; + color:#FFFFFF; +} + +.sliderButtonContainer { + width: 70px; + margin-left:auto; + margin-right:auto; + background-color:#333333; + cursor:pointer; + + @*Rounded Edges*@ + border: 1px solid #444444; + border-top: 0px; + -moz-border-radius-bottomright: 10px; + -webkit-border-bottom-right-radius: 10px; + -moz-border-radius-bottomleft: 10px; + -webkit-border-bottom-left-radius: 10px; +} + +.sliderImage { + width: 16px; + height: 16px; + display: inline-block; + margin-bottom: -3px; + margin-right: -5px; + margin-left: 2px; +} + +.sliderClosed { + background:url('../../Content/Images/ui-icons_2e83ff_256x240.png') -64px -16px no-repeat; +} + +.sliderOpened { + background:url('../../Content/Images/ui-icons_2e83ff_256x240.png') 0px -16px no-repeat; +} \ No newline at end of file diff --git a/NzbDrone.Web/Controllers/SeriesController.cs b/NzbDrone.Web/Controllers/SeriesController.cs index 52a7ebc99..b18e1acfa 100644 --- a/NzbDrone.Web/Controllers/SeriesController.cs +++ b/NzbDrone.Web/Controllers/SeriesController.cs @@ -98,25 +98,17 @@ namespace NzbDrone.Web.Controllers } } - public ActionResult SearchForSeries(string seriesName) + public JsonResult LocalSearch(string term) { - var model = new List(); + //Get Results from the local DB and return - //Get Results from TvDb and convert them to something we can use. - foreach (var tvdbSearchResult in _tvDbProvider.SearchSeries(seriesName)) - { - model.Add(new SeriesSearchResultModel - { - TvDbId = tvdbSearchResult.Id, - TvDbName = tvdbSearchResult.SeriesName, - FirstAired = tvdbSearchResult.FirstAired - }); - } - - //model.Add(new SeriesSearchResultModel{ TvDbId = 12345, TvDbName = "30 Rock", FirstAired = DateTime.Today }); - //model.Add(new SeriesSearchResultModel { TvDbId = 65432, TvDbName = "The Office (US)", FirstAired = DateTime.Today.AddDays(-100) }); + var results = _seriesProvider.SearchForSeries(term).Select(s => new SeriesSearchResultModel + { + Id = s.SeriesId, + Title = s.Title + }).ToList(); - return PartialView("SeriesSearchResults", model); + return Json(results, JsonRequestBehavior.AllowGet); } [HttpPost] diff --git a/NzbDrone.Web/Controllers/SharedController.cs b/NzbDrone.Web/Controllers/SharedController.cs index 38181f2f4..5be4a95ab 100644 --- a/NzbDrone.Web/Controllers/SharedController.cs +++ b/NzbDrone.Web/Controllers/SharedController.cs @@ -25,5 +25,11 @@ namespace NzbDrone.Web.Controllers ViewData["RssTimer"] = _jobProvider.NextScheduledRun(typeof(RssSyncJob)).ToString("yyyyMMddHHmmss"); return PartialView(); } + + [ChildActionOnly] + public ActionResult LocalSearch() + { + return PartialView(); + } } } \ No newline at end of file diff --git a/NzbDrone.Web/Models/SeriesSearchResultModel.cs b/NzbDrone.Web/Models/SeriesSearchResultModel.cs index 3c9a1672a..43258be11 100644 --- a/NzbDrone.Web/Models/SeriesSearchResultModel.cs +++ b/NzbDrone.Web/Models/SeriesSearchResultModel.cs @@ -4,8 +4,8 @@ namespace NzbDrone.Web.Models { public class SeriesSearchResultModel { - public int TvDbId { get; set; } - public string TvDbName { get; set; } + public int Id { get; set; } + public string Title { get; set; } public DateTime FirstAired { get; set; } } } \ No newline at end of file diff --git a/NzbDrone.Web/NzbDrone.Web.csproj b/NzbDrone.Web/NzbDrone.Web.csproj index 89204688f..fac16b2fe 100644 --- a/NzbDrone.Web/NzbDrone.Web.csproj +++ b/NzbDrone.Web/NzbDrone.Web.csproj @@ -329,6 +329,7 @@ + @@ -677,6 +678,7 @@ + @@ -723,7 +725,6 @@ - @@ -932,6 +933,9 @@ + + + \ No newline at end of file + +
+
+ Local Series Search + +
+
+
+ Search
+
+
+
diff --git a/NzbDrone.Web/Views/Shared/LocalSearch.cshtml b/NzbDrone.Web/Views/Shared/LocalSearch.cshtml new file mode 100644 index 000000000..b06f5700e --- /dev/null +++ b/NzbDrone.Web/Views/Shared/LocalSearch.cshtml @@ -0,0 +1,29 @@ +@{ + Layout = null; +} + + + +
+
+ Local Series Search + +
+
+
+ Search
+
+
+
\ No newline at end of file diff --git a/NzbDrone.Web/Views/Shared/_Layout.cshtml b/NzbDrone.Web/Views/Shared/_Layout.cshtml index c8771a6ae..029e1a298 100644 --- a/NzbDrone.Web/Views/Shared/_Layout.cshtml +++ b/NzbDrone.Web/Views/Shared/_Layout.cshtml @@ -15,6 +15,7 @@ + @@ -28,12 +29,14 @@ + @MvcMiniProfiler.MiniProfiler.RenderIncludes() @RenderSection("HeaderContent", required: false)
+ @{Html.RenderAction("LocalSearch", "Shared");}