From d1c6a1322644c1456c91b1a7fbc275757150a160 Mon Sep 17 00:00:00 2001 From: Drewster727 Date: Wed, 6 Apr 2016 18:03:51 -0500 Subject: [PATCH 1/4] #145 firefox css dsplay issue --- PlexRequests.UI/Content/custom.css | 3 ++- PlexRequests.UI/Content/custom.min.css | 2 +- PlexRequests.UI/Content/custom.scss | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/PlexRequests.UI/Content/custom.css b/PlexRequests.UI/Content/custom.css index cd5e95112..520b2cc39 100644 --- a/PlexRequests.UI/Content/custom.css +++ b/PlexRequests.UI/Content/custom.css @@ -192,7 +192,8 @@ label { color: #ccc; } .form-control-search { - padding: 25px 105px 25px 16px; } + padding: 13px 105px 13px 16px; + height: 100%; } .form-control-withbuttons { padding-right: 105px; } diff --git a/PlexRequests.UI/Content/custom.min.css b/PlexRequests.UI/Content/custom.min.css index cd21703d4..34e07289c 100644 --- a/PlexRequests.UI/Content/custom.min.css +++ b/PlexRequests.UI/Content/custom.min.css @@ -1 +1 @@ -@media(min-width:768px){.row{position:relative;}.bottom-align-text{position:absolute;bottom:0;right:0;}}@media(max-width:48em){.home{padding-top:1rem;}}@media(min-width:48em){.home{padding-top:4rem;}}.btn{border-radius:.25rem !important;}.multiSelect{background-color:#4e5d6c;}.form-control-custom{background-color:#4e5d6c !important;color:#fff !important;border-radius:0;box-shadow:0 0 0 !important;}h1{font-size:3.5rem !important;font-weight:600 !important;}.request-title{margin-top:0 !important;font-size:1.9rem !important;}p{font-size:1.1rem !important;}label{display:inline-block !important;margin-bottom:.5rem !important;font-size:16px !important;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background:#4e5d6c;}.navbar .nav a .fa,.dropdown-menu a .fa{font-size:130%;top:1px;position:relative;display:inline-block;margin-right:5px;}.dropdown-menu a .fa{top:2px;}.btn-danger-outline{color:#d9534f !important;background-color:transparent;background-image:none;border-color:#d9534f !important;}.btn-danger-outline:focus,.btn-danger-outline.focus,.btn-danger-outline:active,.btn-danger-outline.active,.btn-danger-outline:hover,.open>.btn-danger-outline.dropdown-toggle{color:#fff !important;background-color:#d9534f !important;border-color:#d9534f !important;}.btn-primary-outline{color:#ff761b !important;background-color:transparent;background-image:none;border-color:#ff761b !important;}.btn-primary-outline:focus,.btn-primary-outline.focus,.btn-primary-outline:active,.btn-primary-outline.active,.btn-primary-outline:hover,.open>.btn-primary-outline.dropdown-toggle{color:#fff !important;background-color:#df691a !important;border-color:#df691a !important;}.btn-info-outline{color:#5bc0de !important;background-color:transparent;background-image:none;border-color:#5bc0de !important;}.btn-info-outline:focus,.btn-info-outline.focus,.btn-info-outline:active,.btn-info-outline.active,.btn-info-outline:hover,.open>.btn-info-outline.dropdown-toggle{color:#fff !important;background-color:#5bc0de !important;border-color:#5bc0de !important;}.btn-warning-outline{color:#f0ad4e !important;background-color:transparent;background-image:none;border-color:#f0ad4e !important;}.btn-warning-outline:focus,.btn-warning-outline.focus,.btn-warning-outline:active,.btn-warning-outline.active,.btn-warning-outline:hover,.open>.btn-warning-outline.dropdown-toggle{color:#fff !important;background-color:#f0ad4e !important;border-color:#f0ad4e !important;}.btn-success-outline{color:#5cb85c !important;background-color:transparent;background-image:none;border-color:#5cb85c !important;}.btn-success-outline:focus,.btn-success-outline.focus,.btn-success-outline:active,.btn-success-outline.active,.btn-success-outline:hover,.open>.btn-success-outline.dropdown-toggle{color:#fff !important;background-color:#5cb85c !important;border-color:#5cb85c !important;}#movieList .mix{display:none;}#tvList .mix{display:none;}.scroll-top-wrapper{position:fixed;opacity:0;visibility:hidden;overflow:hidden;text-align:center;z-index:99999999;background-color:#4e5d6c;color:#eee;width:50px;height:48px;line-height:48px;right:30px;bottom:30px;padding-top:2px;border-top-left-radius:10px;border-top-right-radius:10px;border-bottom-right-radius:10px;border-bottom-left-radius:10px;-webkit-transition:all .5s ease-in-out;-moz-transition:all .5s ease-in-out;-ms-transition:all .5s ease-in-out;-o-transition:all .5s ease-in-out;transition:all .5s ease-in-out;}.scroll-top-wrapper:hover{background-color:#637689;}.scroll-top-wrapper.show{visibility:visible;cursor:pointer;opacity:1;}.scroll-top-wrapper i.fa{line-height:inherit;}.no-search-results{text-align:center;}.no-search-results .no-search-results-icon{font-size:10em;color:#4e5d6c;}.no-search-results .no-search-results-text{margin:20px 0;color:#ccc;}.form-control-search{padding:25px 105px 25px 16px;}.form-control-withbuttons{padding-right:105px;}.input-group-addon .btn-group{position:absolute;right:45px;z-index:3;top:13px;box-shadow:0 0 0;}.input-group-addon .btn-group .btn{border:1px solid rgba(255,255,255,.7) !important;padding:3px 12px;color:rgba(255,255,255,.7) !important;}.btn-split .btn{border-radius:0 !important;}.btn-split .btn:not(.dropdown-toggle){border-radius:.25rem 0 0 .25rem !important;}.btn-split .btn.dropdown-toggle{border-radius:0 .25rem .25rem 0 !important;padding:12px 8px;} \ No newline at end of file +@media(min-width:768px){.row{position:relative;}.bottom-align-text{position:absolute;bottom:0;right:0;}}@media(max-width:48em){.home{padding-top:1rem;}}@media(min-width:48em){.home{padding-top:4rem;}}.btn{border-radius:.25rem !important;}.multiSelect{background-color:#4e5d6c;}.form-control-custom{background-color:#4e5d6c !important;color:#fff !important;border-radius:0;box-shadow:0 0 0 !important;}h1{font-size:3.5rem !important;font-weight:600 !important;}.request-title{margin-top:0 !important;font-size:1.9rem !important;}p{font-size:1.1rem !important;}label{display:inline-block !important;margin-bottom:.5rem !important;font-size:16px !important;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background:#4e5d6c;}.navbar .nav a .fa,.dropdown-menu a .fa{font-size:130%;top:1px;position:relative;display:inline-block;margin-right:5px;}.dropdown-menu a .fa{top:2px;}.btn-danger-outline{color:#d9534f !important;background-color:transparent;background-image:none;border-color:#d9534f !important;}.btn-danger-outline:focus,.btn-danger-outline.focus,.btn-danger-outline:active,.btn-danger-outline.active,.btn-danger-outline:hover,.open>.btn-danger-outline.dropdown-toggle{color:#fff !important;background-color:#d9534f !important;border-color:#d9534f !important;}.btn-primary-outline{color:#ff761b !important;background-color:transparent;background-image:none;border-color:#ff761b !important;}.btn-primary-outline:focus,.btn-primary-outline.focus,.btn-primary-outline:active,.btn-primary-outline.active,.btn-primary-outline:hover,.open>.btn-primary-outline.dropdown-toggle{color:#fff !important;background-color:#df691a !important;border-color:#df691a !important;}.btn-info-outline{color:#5bc0de !important;background-color:transparent;background-image:none;border-color:#5bc0de !important;}.btn-info-outline:focus,.btn-info-outline.focus,.btn-info-outline:active,.btn-info-outline.active,.btn-info-outline:hover,.open>.btn-info-outline.dropdown-toggle{color:#fff !important;background-color:#5bc0de !important;border-color:#5bc0de !important;}.btn-warning-outline{color:#f0ad4e !important;background-color:transparent;background-image:none;border-color:#f0ad4e !important;}.btn-warning-outline:focus,.btn-warning-outline.focus,.btn-warning-outline:active,.btn-warning-outline.active,.btn-warning-outline:hover,.open>.btn-warning-outline.dropdown-toggle{color:#fff !important;background-color:#f0ad4e !important;border-color:#f0ad4e !important;}.btn-success-outline{color:#5cb85c !important;background-color:transparent;background-image:none;border-color:#5cb85c !important;}.btn-success-outline:focus,.btn-success-outline.focus,.btn-success-outline:active,.btn-success-outline.active,.btn-success-outline:hover,.open>.btn-success-outline.dropdown-toggle{color:#fff !important;background-color:#5cb85c !important;border-color:#5cb85c !important;}#movieList .mix{display:none;}#tvList .mix{display:none;}.scroll-top-wrapper{position:fixed;opacity:0;visibility:hidden;overflow:hidden;text-align:center;z-index:99999999;background-color:#4e5d6c;color:#eee;width:50px;height:48px;line-height:48px;right:30px;bottom:30px;padding-top:2px;border-top-left-radius:10px;border-top-right-radius:10px;border-bottom-right-radius:10px;border-bottom-left-radius:10px;-webkit-transition:all .5s ease-in-out;-moz-transition:all .5s ease-in-out;-ms-transition:all .5s ease-in-out;-o-transition:all .5s ease-in-out;transition:all .5s ease-in-out;}.scroll-top-wrapper:hover{background-color:#637689;}.scroll-top-wrapper.show{visibility:visible;cursor:pointer;opacity:1;}.scroll-top-wrapper i.fa{line-height:inherit;}.no-search-results{text-align:center;}.no-search-results .no-search-results-icon{font-size:10em;color:#4e5d6c;}.no-search-results .no-search-results-text{margin:20px 0;color:#ccc;}.form-control-search{padding:13px 105px 13px 16px;height:100%;}.form-control-withbuttons{padding-right:105px;}.input-group-addon .btn-group{position:absolute;right:45px;z-index:3;top:13px;box-shadow:0 0 0;}.input-group-addon .btn-group .btn{border:1px solid rgba(255,255,255,.7) !important;padding:3px 12px;color:rgba(255,255,255,.7) !important;}.btn-split .btn{border-radius:0 !important;}.btn-split .btn:not(.dropdown-toggle){border-radius:.25rem 0 0 .25rem !important;}.btn-split .btn.dropdown-toggle{border-radius:0 .25rem .25rem 0 !important;padding:12px 8px;} \ No newline at end of file diff --git a/PlexRequests.UI/Content/custom.scss b/PlexRequests.UI/Content/custom.scss index 77a7ca1d9..e2324512b 100644 --- a/PlexRequests.UI/Content/custom.scss +++ b/PlexRequests.UI/Content/custom.scss @@ -246,7 +246,8 @@ $border-radius: 10px; } .form-control-search { - padding: 25px 105px 25px 16px; + padding: 13px 105px 13px 16px; + height: 100%; } .form-control-withbuttons { From c6e6583fd5b79ad308e14821a4ccff3f7ffcc518 Mon Sep 17 00:00:00 2001 From: Drewster727 Date: Thu, 7 Apr 2016 00:18:27 -0500 Subject: [PATCH 2/4] #125 start indicating in the results if an item is already requested or available --- PlexRequests.UI/Content/search.js | 15 +- .../Models/SearchMovieViewModel.cs | 50 ++++ .../Models/SearchMusicViewModel.cs | 80 +++--- .../Models/SearchTvShowViewModel.cs | 2 +- PlexRequests.UI/Models/SearchViewModel.cs | 37 +++ PlexRequests.UI/Modules/SearchModule.cs | 250 +++++++++++++++--- PlexRequests.UI/PlexRequests.UI.csproj | 2 + PlexRequests.UI/Views/Search/Index.cshtml | 49 ++-- 8 files changed, 383 insertions(+), 102 deletions(-) create mode 100644 PlexRequests.UI/Models/SearchMovieViewModel.cs create mode 100644 PlexRequests.UI/Models/SearchViewModel.cs diff --git a/PlexRequests.UI/Content/search.js b/PlexRequests.UI/Content/search.js index 1096290ed..610f1399d 100644 --- a/PlexRequests.UI/Content/search.js +++ b/PlexRequests.UI/Content/search.js @@ -274,7 +274,10 @@ $(function () { voteAverage: result.voteAverage, year: year, type: "movie", - imdb: result.imdbId + imdb: result.imdbId, + requested: result.requested, + approved: result.approved, + available: result.available }; return context; @@ -290,7 +293,10 @@ $(function () { overview: result.overview, year: year, type: "tv", - imdb: result.imdbId + imdb: result.imdbId, + requested: result.requested, + approved: result.approved, + available: result.available }; return context; } @@ -307,7 +313,10 @@ $(function () { coverArtUrl: result.coverArtUrl, artist: result.artist, releaseType: result.releaseType, - country: result.country + country: result.country, + requested: result.requested, + approved: result.approved, + available: result.available }; return context; diff --git a/PlexRequests.UI/Models/SearchMovieViewModel.cs b/PlexRequests.UI/Models/SearchMovieViewModel.cs new file mode 100644 index 000000000..dc7c51a33 --- /dev/null +++ b/PlexRequests.UI/Models/SearchMovieViewModel.cs @@ -0,0 +1,50 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: SearchTvShowViewModel.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using System; +using System.Collections.Generic; + +namespace PlexRequests.UI.Models +{ + public class SearchMovieViewModel : SearchViewModel + { + public bool Adult { get; set; } + public string BackdropPath { get; set; } + public List GenreIds { get; set; } + public int Id { get; set; } + public string OriginalLanguage { get; set; } + public string OriginalTitle { get; set; } + public string Overview { get; set; } + public double Popularity { get; set; } + public string PosterPath { get; set; } + public DateTime? ReleaseDate { get; set; } + public string Title { get; set; } + public bool Video { get; set; } + public double VoteAverage { get; set; } + public int VoteCount { get; set; } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Models/SearchMusicViewModel.cs b/PlexRequests.UI/Models/SearchMusicViewModel.cs index 94d3e6d1e..66d140a12 100644 --- a/PlexRequests.UI/Models/SearchMusicViewModel.cs +++ b/PlexRequests.UI/Models/SearchMusicViewModel.cs @@ -1,41 +1,41 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: SearchMusicViewModel.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion -namespace PlexRequests.UI.Models -{ - public class SearchMusicViewModel - { - public string Id { get; set; } - public string Overview { get; set; } - public string CoverArtUrl { get; set; } - public string Title { get; set; } - public string Artist { get; set; } - public string ReleaseDate { get; set; } - public int TrackCount { get; set; } - public string ReleaseType { get; set; } - public string Country { get; set; } - } +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: SearchMusicViewModel.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +namespace PlexRequests.UI.Models +{ + public class SearchMusicViewModel : SearchViewModel + { + public string Id { get; set; } + public string Overview { get; set; } + public string CoverArtUrl { get; set; } + public string Title { get; set; } + public string Artist { get; set; } + public string ReleaseDate { get; set; } + public int TrackCount { get; set; } + public string ReleaseType { get; set; } + public string Country { get; set; } + } } \ No newline at end of file diff --git a/PlexRequests.UI/Models/SearchTvShowViewModel.cs b/PlexRequests.UI/Models/SearchTvShowViewModel.cs index ee6de42d1..2ed46beff 100644 --- a/PlexRequests.UI/Models/SearchTvShowViewModel.cs +++ b/PlexRequests.UI/Models/SearchTvShowViewModel.cs @@ -29,7 +29,7 @@ using System.Collections.Generic; namespace PlexRequests.UI.Models { - public class SearchTvShowViewModel + public class SearchTvShowViewModel : SearchViewModel { public int Id { get; set; } public string SeriesName { get; set; } diff --git a/PlexRequests.UI/Models/SearchViewModel.cs b/PlexRequests.UI/Models/SearchViewModel.cs new file mode 100644 index 000000000..776b9d2b1 --- /dev/null +++ b/PlexRequests.UI/Models/SearchViewModel.cs @@ -0,0 +1,37 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: SearchTvShowViewModel.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + + +namespace PlexRequests.UI.Models +{ + public class SearchViewModel + { + public bool Approved { get; set; } + public bool Requested { get; set; } + public bool Available { get; set; } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/SearchModule.cs b/PlexRequests.UI/Modules/SearchModule.cs index 5b541091c..7e001c489 100644 --- a/PlexRequests.UI/Modules/SearchModule.cs +++ b/PlexRequests.UI/Modules/SearchModule.cs @@ -48,6 +48,9 @@ using PlexRequests.Services.Notification; using PlexRequests.Store; using PlexRequests.UI.Helpers; using PlexRequests.UI.Models; +using System.Threading.Tasks; +using TMDbLib.Objects.Search; +using PlexRequests.Api.Models.Tv; namespace PlexRequests.UI.Modules { @@ -109,7 +112,8 @@ namespace PlexRequests.UI.Modules private IHeadphonesApi HeadphonesApi { get; } private static Logger Log = LogManager.GetCurrentClassLogger(); - private bool IsAdmin { + private bool IsAdmin + { get { return Context.CurrentUser.IsAuthenticated(); @@ -124,29 +128,168 @@ namespace PlexRequests.UI.Modules return View["Search/Index", settings]; } + private Response UpcomingMovies() + { + Log.Trace("Loading upcoming movies"); + + return ProcessMovies(new Task>(() => + { + return MovieApi.GetUpcomingMovies().Result.Select(x => new SearchMovie() + { + Adult = x.Adult, + BackdropPath = x.BackdropPath, + GenreIds = x.GenreIds, + Id = x.Id, + OriginalLanguage = x.OriginalLanguage, + OriginalTitle = x.OriginalTitle, + Overview = x.Overview, + Popularity = x.Popularity, + PosterPath = x.PosterPath, + ReleaseDate = x.ReleaseDate, + Title = x.Title, + Video = x.Video, + VoteAverage = x.VoteAverage, + VoteCount = x.VoteCount + }).ToList(); + })); + } + + private Response CurrentlyPlayingMovies() + { + Log.Trace("Loading currently playing movies"); + + return ProcessMovies(new Task>(() => + { + return MovieApi.GetCurrentPlayingMovies().Result.Select(x => new SearchMovie() + { + Adult = x.Adult, + BackdropPath = x.BackdropPath, + GenreIds = x.GenreIds, + Id = x.Id, + OriginalLanguage = x.OriginalLanguage, + OriginalTitle = x.OriginalTitle, + Overview = x.Overview, + Popularity = x.Popularity, + PosterPath = x.PosterPath, + ReleaseDate = x.ReleaseDate, + Title = x.Title, + Video = x.Video, + VoteAverage = x.VoteAverage, + VoteCount = x.VoteCount + }).ToList(); + })); + } + private Response SearchMovie(string searchTerm) { Log.Trace("Searching for Movie {0}", searchTerm); - var movies = MovieApi.SearchMovie(searchTerm); - var result = movies.Result; - return Response.AsJson(result); + + return ProcessMovies(new Task>(() => + { + return MovieApi.SearchMovie(searchTerm).Result; + })); + } + + private Response ProcessMovies(Task> apiTask) + { + List taskList = new List(); + + List apiMovies = new List(); + + apiTask.ContinueWith((t) => + { + apiMovies = t.Result; + }); + taskList.Add(apiTask); + apiTask.Start(); + + Dictionary dbMovies = new Dictionary(); + taskList.Add(Task.Factory.StartNew(() => + { + return RequestService.GetAll().Where(x => x.Type == RequestType.Movie); + + }).ContinueWith((t) => + { + dbMovies = t.Result.ToDictionary(x => x.ProviderId); + })); + + Task.WaitAll(taskList.ToArray()); + + List viewMovies = new List(); + foreach (SearchMovie movie in apiMovies) + { + var viewMovie = new SearchMovieViewModel() + { + Adult = movie.Adult, + BackdropPath = movie.BackdropPath, + GenreIds = movie.GenreIds, + Id = movie.Id, + OriginalLanguage = movie.OriginalLanguage, + OriginalTitle = movie.OriginalTitle, + Overview = movie.Overview, + Popularity = movie.Popularity, + PosterPath = movie.PosterPath, + ReleaseDate = movie.ReleaseDate, + Title = movie.Title, + Video = movie.Video, + VoteAverage = movie.VoteAverage, + VoteCount = movie.VoteCount + }; + + if (dbMovies.ContainsKey(movie.Id)) + { + var dbm = dbMovies[movie.Id]; + + viewMovie.Requested = true; + viewMovie.Approved = dbm.Approved; + viewMovie.Available = dbm.Available; + } + + viewMovies.Add(viewMovie); + } + + return Response.AsJson(viewMovies); } private Response SearchTvShow(string searchTerm) { Log.Trace("Searching for TV Show {0}", searchTerm); - //var tvShow = TvApi.SearchTv(searchTerm, AuthToken); - var tvShow = new TvMazeApi().Search(searchTerm); - if (!tvShow.Any()) + + List taskList = new List(); + + List apiTv = new List(); + taskList.Add(Task.Factory.StartNew(() => + { + return new TvMazeApi().Search(searchTerm); + + }).ContinueWith((t) => + { + apiTv = t.Result; + })); + + Dictionary dbTv = new Dictionary(); + taskList.Add(Task.Factory.StartNew(() => + { + return RequestService.GetAll().Where(x => x.Type == RequestType.TvShow); + + }).ContinueWith((t) => + { + dbTv = t.Result.ToDictionary(x => x.ProviderId); + })); + + Task.WaitAll(taskList.ToArray()); + + if (!apiTv.Any()) { Log.Trace("TV Show data is null"); return Response.AsJson(""); } - var model = new List(); - foreach (var t in tvShow) + + var viewTv = new List(); + foreach (var t in apiTv) { - model.Add(new SearchTvShowViewModel + var viewT = new SearchTvShowViewModel { // We are constructing the banner with the id: // http://thetvdb.com/banners/_cache/posters/ID-1.jpg @@ -161,24 +304,56 @@ namespace PlexRequests.UI.Modules Runtime = t.show.runtime.ToString(), SeriesId = t.show.id, SeriesName = t.show.name, + Status = t.show.status + }; - Status = t.show.status, - }); + if (t.show.externals.thetvdb != null && dbTv.ContainsKey((int)t.show.externals.thetvdb)) + { + var dbt = dbTv[(int)t.show.externals.thetvdb]; + + viewT.Requested = true; + viewT.Approved = dbt.Approved; + viewT.Available = dbt.Available; + } + + viewTv.Add(viewT); } Log.Trace("Returning TV Show results: "); - Log.Trace(model.DumpJson()); - return Response.AsJson(model); + Log.Trace(viewTv.DumpJson()); + return Response.AsJson(viewTv); } private Response SearchMusic(string searchTerm) { - var albums = MusicBrainzApi.SearchAlbum(searchTerm); - var releases = albums.releases ?? new List(); - var model = new List(); - foreach (var a in releases) + List taskList = new List(); + + List apiAlbums = new List(); + taskList.Add(Task.Factory.StartNew(() => + { + return MusicBrainzApi.SearchAlbum(searchTerm); + + }).ContinueWith((t) => { - model.Add(new SearchMusicViewModel + apiAlbums = t.Result.releases ?? new List(); + })); + + Dictionary dbAlbum = new Dictionary(); + taskList.Add(Task.Factory.StartNew(() => + { + return RequestService.GetAll().Where(x => x.Type == RequestType.Album); + + }).ContinueWith((t) => + { + dbAlbum = t.Result.ToDictionary(x => x.MusicBrainzId); + })); + + Task.WaitAll(taskList.ToArray()); + + var viewAlbum = new List(); + foreach (var a in apiAlbums) + { + var viewA = new SearchMusicViewModel { Title = a.title, Id = a.id, @@ -188,27 +363,20 @@ namespace PlexRequests.UI.Modules TrackCount = a.TrackCount, ReleaseType = a.status, Country = a.country - }); - } - return Response.AsJson(model); - } + }; - private Response UpcomingMovies() // TODO : Not used - { - var movies = MovieApi.GetUpcomingMovies(); - var result = movies.Result; - Log.Trace("Movie Upcoming Results: "); - Log.Trace(result.DumpJson()); - return Response.AsJson(result); - } + if (!string.IsNullOrEmpty(a.id) && dbAlbum.ContainsKey(a.id)) + { + var dba = dbAlbum[a.id]; - private Response CurrentlyPlayingMovies() // TODO : Not used - { - var movies = MovieApi.GetCurrentPlayingMovies(); - var result = movies.Result; - Log.Trace("Movie Currently Playing Results: "); - Log.Trace(result.DumpJson()); - return Response.AsJson(result); + viewA.Requested = true; + viewA.Approved = dba.Approved; + viewA.Available = dba.Available; + } + + viewAlbum.Add(viewA); + } + return Response.AsJson(viewAlbum); } private Response RequestMovie(int movieId) @@ -241,7 +409,7 @@ namespace PlexRequests.UI.Modules try { - if (CheckIfTitleExistsInPlex(movieInfo.Title, movieInfo.ReleaseDate?.Year.ToString(),null, PlexType.Movie)) + if (CheckIfTitleExistsInPlex(movieInfo.Title, movieInfo.ReleaseDate?.Year.ToString(), null, PlexType.Movie)) { return Response.AsJson(new JsonResponseModel { Result = false, Message = $"{fullMovieName} is already in Plex!" }); } @@ -502,7 +670,7 @@ namespace PlexRequests.UI.Modules Log.Debug("This is a new request"); - + var albumInfo = MusicBrainzApi.GetAlbum(releaseId); DateTime release; DateTimeHelper.CustomParse(albumInfo.ReleaseEvents?.FirstOrDefault()?.date, out release); @@ -581,7 +749,7 @@ namespace PlexRequests.UI.Modules Message = $"{model.Title} was successfully added!" }); } - + var result = RequestService.AddRequest(model); return Response.AsJson(new JsonResponseModel { diff --git a/PlexRequests.UI/PlexRequests.UI.csproj b/PlexRequests.UI/PlexRequests.UI.csproj index e822b1a70..e7076ef55 100644 --- a/PlexRequests.UI/PlexRequests.UI.csproj +++ b/PlexRequests.UI/PlexRequests.UI.csproj @@ -170,7 +170,9 @@ + + diff --git a/PlexRequests.UI/Views/Search/Index.cshtml b/PlexRequests.UI/Views/Search/Index.cshtml index e5c316a79..3f89e1c14 100644 --- a/PlexRequests.UI/Views/Search/Index.cshtml +++ b/PlexRequests.UI/Views/Search/Index.cshtml @@ -124,21 +124,29 @@
- {{#if_eq type "movie"}} - - {{/if_eq}} - {{#if_eq type "tv"}} - + {{#if_eq available true}} + + {{else}} + {{#if_eq requested true}} + + {{else}} + {{#if_eq type "movie"}} + + {{/if_eq}} + {{#if_eq type "tv"}} + + {{/if_eq}} + {{/if_eq}} {{/if_eq}}

@@ -181,8 +189,15 @@
- - + {{#if_eq available true}} + + {{else}} + {{#if_eq requested true}} + + {{else}} + + {{/if_eq}} + {{/if_eq}}
Track Count: {{trackCount}} Country: {{country}} From a6695db590492bee2da390aab49096c863cb9d3b Mon Sep 17 00:00:00 2001 From: Drewster727 Date: Thu, 7 Apr 2016 09:08:23 -0500 Subject: [PATCH 3/4] fix search spinner sticking around after clearing search text + make the "Requested" and "Available" indicators in the search page different colors --- PlexRequests.UI/Content/search.js | 31 +++++++++++++++-------- PlexRequests.UI/Views/Search/Index.cshtml | 2 +- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/PlexRequests.UI/Content/search.js b/PlexRequests.UI/Content/search.js index 610f1399d..b4ae49fcf 100644 --- a/PlexRequests.UI/Content/search.js +++ b/PlexRequests.UI/Content/search.js @@ -30,7 +30,6 @@ $(function () { if (searchTimer) { clearTimeout(searchTimer); } - $('#movieSearchButton').attr("class", "fa fa-spinner fa-spin"); searchTimer = setTimeout(movieSearch, 400); }); @@ -50,7 +49,6 @@ $(function () { if (searchTimer) { clearTimeout(searchTimer); } - $('#tvSearchButton').attr("class", "fa fa-spinner fa-spin"); searchTimer = setTimeout(tvSearch, 400); }); @@ -90,7 +88,6 @@ $(function () { if (searchTimer) { clearTimeout(searchTimer); } - $('#musicSearchButton').attr("class", "fa fa-spinner fa-spin"); searchTimer = setTimeout(musicSearch, 400); }); @@ -175,7 +172,7 @@ $(function () { function movieSearch() { var query = $("#movieSearchContent").val(); - getMovies("/search/movie/" + query); + query ? getMovies("/search/movie/" + query) : resetMovies(); } function moviesComingSoon() { @@ -187,9 +184,9 @@ $(function () { } function getMovies(url) { - $("#movieList").html(""); - + resetMovies(); + $('#movieSearchButton').attr("class", "fa fa-spinner fa-spin"); $.ajax(url).success(function (results) { if (results.length > 0) { results.forEach(function (result) { @@ -206,14 +203,19 @@ $(function () { }); }; + function resetMovies() { + $("#movieList").html(""); + } + function tvSearch() { var query = $("#tvSearchContent").val(); - getTvShows("/search/tv/" + query); + query ? getTvShows("/search/tv/" + query) : resetTvShows(); } function getTvShows(url) { - $("#tvList").html(""); + resetTvShows(); + $('#tvSearchButton').attr("class", "fa fa-spinner fa-spin"); $.ajax(url).success(function (results) { if (results.length > 0) { results.forEach(function (result) { @@ -229,14 +231,19 @@ $(function () { }); }; + function resetTvShows() { + $("#tvList").html(""); + } + function musicSearch() { var query = $("#musicSearchContent").val(); - getMusic("/search/music/" + query); + query ? getMusic("/search/music/" + query) : resetMusic(); } function getMusic(url) { - $("#musicList").html(""); + resetMusic(); + $('#musicSearchButton').attr("class", "fa fa-spinner fa-spin"); $.ajax(url).success(function (results) { if (results.length > 0) { results.forEach(function (result) { @@ -254,6 +261,10 @@ $(function () { }); }; + function resetMusic() { + $("#musicList").html(""); + } + function getCoverArt(artistId) { $.ajax("/search/music/coverart/" + artistId).success(function (result) { if (result) { diff --git a/PlexRequests.UI/Views/Search/Index.cshtml b/PlexRequests.UI/Views/Search/Index.cshtml index 3f89e1c14..8d2726b44 100644 --- a/PlexRequests.UI/Views/Search/Index.cshtml +++ b/PlexRequests.UI/Views/Search/Index.cshtml @@ -128,7 +128,7 @@ {{else}} {{#if_eq requested true}} - + {{else}} {{#if_eq type "movie"}} From 33de634ade16a68c2af22237c725fb3dbf598f76 Mon Sep 17 00:00:00 2001 From: Drewster727 Date: Thu, 7 Apr 2016 14:29:23 -0500 Subject: [PATCH 4/4] #125 refactor async task logic to work with mono --- PlexRequests.UI/Models/MovieSearchType.cs | 35 +++++++++ PlexRequests.UI/Modules/SearchModule.cs | 93 +++++++++-------------- PlexRequests.UI/PlexRequests.UI.csproj | 1 + 3 files changed, 74 insertions(+), 55 deletions(-) create mode 100644 PlexRequests.UI/Models/MovieSearchType.cs diff --git a/PlexRequests.UI/Models/MovieSearchType.cs b/PlexRequests.UI/Models/MovieSearchType.cs new file mode 100644 index 000000000..9441ee15f --- /dev/null +++ b/PlexRequests.UI/Models/MovieSearchType.cs @@ -0,0 +1,35 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: PlexType.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +namespace PlexRequests.UI.Models +{ + public enum MovieSearchType + { + Upcoming, + CurrentlyPlaying, + Search + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/SearchModule.cs b/PlexRequests.UI/Modules/SearchModule.cs index 7e001c489..a35a05055 100644 --- a/PlexRequests.UI/Modules/SearchModule.cs +++ b/PlexRequests.UI/Modules/SearchModule.cs @@ -51,6 +51,7 @@ using PlexRequests.UI.Models; using System.Threading.Tasks; using TMDbLib.Objects.Search; using PlexRequests.Api.Models.Tv; +using TMDbLib.Objects.General; namespace PlexRequests.UI.Modules { @@ -131,77 +132,59 @@ namespace PlexRequests.UI.Modules private Response UpcomingMovies() { Log.Trace("Loading upcoming movies"); - - return ProcessMovies(new Task>(() => - { - return MovieApi.GetUpcomingMovies().Result.Select(x => new SearchMovie() - { - Adult = x.Adult, - BackdropPath = x.BackdropPath, - GenreIds = x.GenreIds, - Id = x.Id, - OriginalLanguage = x.OriginalLanguage, - OriginalTitle = x.OriginalTitle, - Overview = x.Overview, - Popularity = x.Popularity, - PosterPath = x.PosterPath, - ReleaseDate = x.ReleaseDate, - Title = x.Title, - Video = x.Video, - VoteAverage = x.VoteAverage, - VoteCount = x.VoteCount - }).ToList(); - })); + return ProcessMovies(MovieSearchType.Upcoming, string.Empty); } private Response CurrentlyPlayingMovies() { Log.Trace("Loading currently playing movies"); - - return ProcessMovies(new Task>(() => - { - return MovieApi.GetCurrentPlayingMovies().Result.Select(x => new SearchMovie() - { - Adult = x.Adult, - BackdropPath = x.BackdropPath, - GenreIds = x.GenreIds, - Id = x.Id, - OriginalLanguage = x.OriginalLanguage, - OriginalTitle = x.OriginalTitle, - Overview = x.Overview, - Popularity = x.Popularity, - PosterPath = x.PosterPath, - ReleaseDate = x.ReleaseDate, - Title = x.Title, - Video = x.Video, - VoteAverage = x.VoteAverage, - VoteCount = x.VoteCount - }).ToList(); - })); + return ProcessMovies(MovieSearchType.CurrentlyPlaying, string.Empty); } private Response SearchMovie(string searchTerm) { Log.Trace("Searching for Movie {0}", searchTerm); - - return ProcessMovies(new Task>(() => - { - return MovieApi.SearchMovie(searchTerm).Result; - })); + return ProcessMovies(MovieSearchType.Search, searchTerm); } - private Response ProcessMovies(Task> apiTask) + private Response ProcessMovies(MovieSearchType searchType, string searchTerm) { List taskList = new List(); - List apiMovies = new List(); - - apiTask.ContinueWith((t) => + List apiMovies = new List(); + taskList.Add(Task.Factory.StartNew>(() => + { + switch(searchType) + { + case MovieSearchType.Search: + return MovieApi.SearchMovie(searchTerm).Result.Select(x => new MovieResult() + { + Adult = x.Adult, + BackdropPath = x.BackdropPath, + GenreIds = x.GenreIds, + Id = x.Id, + OriginalLanguage = x.OriginalLanguage, + OriginalTitle = x.OriginalTitle, + Overview = x.Overview, + Popularity = x.Popularity, + PosterPath = x.PosterPath, + ReleaseDate = x.ReleaseDate, + Title = x.Title, + Video = x.Video, + VoteAverage = x.VoteAverage, + VoteCount = x.VoteCount + }).ToList(); + case MovieSearchType.CurrentlyPlaying: + return MovieApi.GetCurrentPlayingMovies().Result.ToList(); + case MovieSearchType.Upcoming: + return MovieApi.GetUpcomingMovies().Result.ToList(); + default: + return new List(); + } + }).ContinueWith((t) => { apiMovies = t.Result; - }); - taskList.Add(apiTask); - apiTask.Start(); + })); Dictionary dbMovies = new Dictionary(); taskList.Add(Task.Factory.StartNew(() => @@ -216,7 +199,7 @@ namespace PlexRequests.UI.Modules Task.WaitAll(taskList.ToArray()); List viewMovies = new List(); - foreach (SearchMovie movie in apiMovies) + foreach (MovieResult movie in apiMovies) { var viewMovie = new SearchMovieViewModel() { diff --git a/PlexRequests.UI/PlexRequests.UI.csproj b/PlexRequests.UI/PlexRequests.UI.csproj index e7076ef55..7d4cbfb9a 100644 --- a/PlexRequests.UI/PlexRequests.UI.csproj +++ b/PlexRequests.UI/PlexRequests.UI.csproj @@ -169,6 +169,7 @@ +