From 9ac949a67cba9c14aded388afd7272a5d628d078 Mon Sep 17 00:00:00 2001 From: Drewster727 Date: Sun, 3 Apr 2016 17:30:12 -0500 Subject: [PATCH] #114 first pass at choosing quality profile when approving + focus search input by default and when switching tabs --- .../SettingModels/SickRageSettings.cs | 18 +++ PlexRequests.UI/Content/custom.css | 10 ++ PlexRequests.UI/Content/custom.min.css | 2 +- PlexRequests.UI/Content/custom.scss | 13 ++ PlexRequests.UI/Content/requests.js | 93 ++++++++---- PlexRequests.UI/Content/search.js | 11 +- PlexRequests.UI/Content/site.js | 22 ++- PlexRequests.UI/Helpers/TvSender.cs | 25 +++- PlexRequests.UI/Models/QualityModel.cs | 8 ++ PlexRequests.UI/Models/RequestViewModel.cs | 1 + PlexRequests.UI/Modules/ApprovalModule.cs | 19 +-- PlexRequests.UI/Modules/RequestsModule.cs | 133 ++++++++++++++++-- PlexRequests.UI/PlexRequests.UI.csproj | 1 + PlexRequests.UI/Views/Admin/Sickrage.cshtml | 13 +- PlexRequests.UI/Views/Requests/Index.cshtml | 19 ++- PlexRequests.UI/Views/Search/Index.cshtml | 12 +- 16 files changed, 324 insertions(+), 76 deletions(-) create mode 100644 PlexRequests.UI/Models/QualityModel.cs diff --git a/PlexRequests.Core/SettingModels/SickRageSettings.cs b/PlexRequests.Core/SettingModels/SickRageSettings.cs index 657de3b50..b36a7bc70 100644 --- a/PlexRequests.Core/SettingModels/SickRageSettings.cs +++ b/PlexRequests.Core/SettingModels/SickRageSettings.cs @@ -28,6 +28,7 @@ using System; using Newtonsoft.Json; using PlexRequests.Helpers; +using System.Collections.Generic; namespace PlexRequests.Core.SettingModels { @@ -40,6 +41,23 @@ namespace PlexRequests.Core.SettingModels public string QualityProfile { get; set; } public bool Ssl { get; set; } public string SubDir { get; set; } + public Dictionary Qualities + { + get + { + return new Dictionary() { + { "default", "Use Deafult" }, + { "sdtv", ">SD TV" }, + { "sddvd", "SD DVD" }, + { "hdtv", "HD TV" }, + { "rawhdtv", "Raw HD TV" }, + { "hdwebdl", "HD Web DL" }, + { "fullhdwebdl", "Full HD Web DL" }, + { "hdbluray", "HD Bluray" }, + { "fullhdbluray", "Full HD Bluray" } + }; + } + } [JsonIgnore] public Uri FullUri diff --git a/PlexRequests.UI/Content/custom.css b/PlexRequests.UI/Content/custom.css index 66153a87a..cd5e95112 100644 --- a/PlexRequests.UI/Content/custom.css +++ b/PlexRequests.UI/Content/custom.css @@ -209,3 +209,13 @@ label { padding: 3px 12px; color: rgba(255, 255, 255, 0.7) !important; } +.btn-split .btn { + border-radius: 0 !important; } + +.btn-split .btn:not(.dropdown-toggle) { + border-radius: 0.25rem 0 0 0.25rem !important; } + +.btn-split .btn.dropdown-toggle { + border-radius: 0 0.25rem 0.25rem 0 !important; + padding: 12px 8px; } + diff --git a/PlexRequests.UI/Content/custom.min.css b/PlexRequests.UI/Content/custom.min.css index 9f60b69e2..cd21703d4 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;} \ 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: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 diff --git a/PlexRequests.UI/Content/custom.scss b/PlexRequests.UI/Content/custom.scss index 4c42a8dfc..77a7ca1d9 100644 --- a/PlexRequests.UI/Content/custom.scss +++ b/PlexRequests.UI/Content/custom.scss @@ -266,3 +266,16 @@ $border-radius: 10px; 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 $i; +} + +.btn-split .btn.dropdown-toggle { + border-radius: 0 .25rem .25rem 0 $i; + padding: 12px 8px; +} \ No newline at end of file diff --git a/PlexRequests.UI/Content/requests.js b/PlexRequests.UI/Content/requests.js index 611d89fba..de5fd12de 100644 --- a/PlexRequests.UI/Content/requests.js +++ b/PlexRequests.UI/Content/requests.js @@ -1,8 +1,8 @@ Handlebars.registerHelper('if_eq', function (a, b, opts) { if (a == b) - return opts.fn(this); + return !opts ? null : opts.fn(this); else - return opts.inverse(this); + return !opts ? null : opts.inverse(this); }); var searchSource = $("#search-template").html(); @@ -268,37 +268,44 @@ $(document).on("click", ".delete", function (e) { // Approve single request $(document).on("click", ".approve", function (e) { e.preventDefault(); - var buttonId = e.target.id; - var $form = $('#approve' + buttonId); + var $this = $(this); + var $form = $this.parents('form').first(); - if ($('#' + buttonId).text() === " Loading...") { + if ($this.text() === " Loading...") { return; } - loadingButton(buttonId, "success"); + loadingButton($this.attr('id'), "success"); - $.ajax({ - type: $form.prop('method'), - url: $form.prop('action'), - data: $form.serialize(), - dataType: "json", - success: function (response) { + approveRequest($form, null, function () { + $("#" + $this.attr('id') + "notapproved").prop("class", "fa fa-check"); + + var $group = $this.parent('.btn-split'); + if ($group.length > 0) { + $group.remove(); + } + else { + $this.remove(); + } + }); +}); - if (checkJsonResponse(response)) { - if (response.message) { - generateNotify(response.message, "success"); - } else { - generateNotify("Success! Request Approved.", "success"); - } +$(document).on("click", ".approve-with-quality", function (e) { + e.preventDefault(); + var $this = $(this); + var $button = $this.parents('.btn-split').children('.approve').first(); + var qualityId = e.target.id + var $form = $this.parents('form').first(); + + if ($button.text() === " Loading...") { + return; + } - $("button[custom-button='" + buttonId + "']").remove(); - $("#" + buttonId + "notapproved").prop("class", "fa fa-check"); - } - }, - error: function (e) { - console.log(e); - generateNotify("Something went wrong!", "danger"); - } + loadingButton($button.attr('id'), "success"); + + approveRequest($form, qualityId, function () { + $("#" + $button.attr('id') + "notapproved").prop("class", "fa fa-check"); + $this.parents('.btn-split').remove(); }); }); @@ -372,6 +379,37 @@ $(document).on("click", ".change", function (e) { }); +function approveRequest($form, qualityId, successCallback) { + + var formData = $form.serialize(); + if (qualityId) formData += ("&qualityId=" + qualityId); + + $.ajax({ + type: $form.prop('method'), + url: $form.prop('action'), + data: formData, + dataType: "json", + success: function (response) { + + if (checkJsonResponse(response)) { + if (response.message) { + generateNotify(response.message, "success"); + } else { + generateNotify("Success! Request Approved.", "success"); + } + + if (successCallback) { + successCallback(); + } + } + }, + error: function (e) { + console.log(e); + generateNotify("Something went wrong!", "danger"); + } + }); +} + function mixItUpConfig(activeState) { var conf = mixItUpDefault; @@ -483,7 +521,8 @@ function buildRequestContext(result, type) { imdb: result.imdbId, seriesRequested: result.tvSeriesRequestType, coverArtUrl: result.coverArtUrl, - + qualities: result.qualities, + hasQualities: result.qualities && result.qualities.length > 0 }; return context; diff --git a/PlexRequests.UI/Content/search.js b/PlexRequests.UI/Content/search.js index 4dfb7dc12..c2d43ee17 100644 --- a/PlexRequests.UI/Content/search.js +++ b/PlexRequests.UI/Content/search.js @@ -20,6 +20,10 @@ $(function () { $tabs.first().children('a:first-child').tab('show'); } + $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { + focusSearch($($(e.target).attr('href'))) + }); + focusSearch($('li.active a', '#nav-tabs').first().attr('href')); // Type in movie search $("#movieSearchContent").on("input", function () { @@ -132,9 +136,14 @@ $(function () { var data = $form.serialize(); sendRequestAjax(data, type, url, buttonId); - }); + function focusSearch($content) { + if ($content.length > 0) { + $('input[type=text].form-control', $content).first().focus(); + } + } + function sendRequestAjax(data, type, url, buttonId) { $.ajax({ type: type, diff --git a/PlexRequests.UI/Content/site.js b/PlexRequests.UI/Content/site.js index 72ec831fa..69602d059 100644 --- a/PlexRequests.UI/Content/site.js +++ b/PlexRequests.UI/Content/site.js @@ -35,15 +35,25 @@ function checkJsonResponse(response) { } function loadingButton(elementId, originalCss) { - $('#' + elementId).removeClass("btn-" + originalCss + "-outline"); - $('#' + elementId).addClass("btn-primary-outline"); - $('#' + elementId).html(" Loading..."); + var $element = $('#' + elementId); + $element.removeClass("btn-" + originalCss + "-outline").addClass("btn-primary-outline").addClass('disabled').html(" Loading..."); + + // handle split-buttons + var $dropdown = $element.next('.dropdown-toggle') + if ($dropdown.length > 0) { + $dropdown.removeClass("btn-" + originalCss + "-outline").addClass("btn-primary-outline").addClass('disabled'); + } } function finishLoading(elementId, originalCss, html) { - $('#' + elementId).removeClass("btn-primary-outline"); - $('#' + elementId).addClass("btn-" + originalCss + "-outline"); - $('#' + elementId).html(html); + var $element = $('#' + elementId); + $element.removeClass("btn-primary-outline").removeClass('disabled').addClass("btn-" + originalCss + "-outline").html(html); + + // handle split-buttons + var $dropdown = $element.next('.dropdown-toggle') + if ($dropdown.length > 0) { + $dropdown.removeClass("btn-primary-outline").removeClass('disabled').addClass("btn-" + originalCss + "-outline"); + } } var noResultsHtml = "
" + diff --git a/PlexRequests.UI/Helpers/TvSender.cs b/PlexRequests.UI/Helpers/TvSender.cs index 703c813fd..b361c7f98 100644 --- a/PlexRequests.UI/Helpers/TvSender.cs +++ b/PlexRequests.UI/Helpers/TvSender.cs @@ -31,6 +31,7 @@ using PlexRequests.Api.Models.Sonarr; using PlexRequests.Core.SettingModels; using PlexRequests.Helpers; using PlexRequests.Store; +using System.Linq; namespace PlexRequests.UI.Helpers { @@ -46,9 +47,19 @@ namespace PlexRequests.UI.Helpers private static Logger Log = LogManager.GetCurrentClassLogger(); public SonarrAddSeries SendToSonarr(SonarrSettings sonarrSettings, RequestedModel model) + { + return SendToSonarr(sonarrSettings, model, string.Empty); + } + + public SonarrAddSeries SendToSonarr(SonarrSettings sonarrSettings, RequestedModel model, string qualityId) { int qualityProfile; - int.TryParse(sonarrSettings.QualityProfile, out qualityProfile); + + if (!string.IsNullOrEmpty(qualityId) || !int.TryParse(qualityId, out qualityProfile)) // try to parse the passed in quality, otherwise use the settings default quality + { + int.TryParse(sonarrSettings.QualityProfile, out qualityProfile); + } + var result = SonarrApi.AddSeries(model.ProviderId, model.Title, qualityProfile, sonarrSettings.SeasonFolders, sonarrSettings.RootPath, model.SeasonCount, model.SeasonList, sonarrSettings.ApiKey, sonarrSettings.FullUri); @@ -61,7 +72,17 @@ namespace PlexRequests.UI.Helpers public SickRageTvAdd SendToSickRage(SickRageSettings sickRageSettings, RequestedModel model) { - var result = SickrageApi.AddSeries(model.ProviderId, model.SeasonCount, model.SeasonList, sickRageSettings.QualityProfile, + return SendToSickRage(sickRageSettings, model, sickRageSettings.QualityProfile); + } + + public SickRageTvAdd SendToSickRage(SickRageSettings sickRageSettings, RequestedModel model, string qualityId) + { + if (!sickRageSettings.Qualities.Any(x => x.Key == qualityId)) + { + qualityId = sickRageSettings.QualityProfile; + } + + var result = SickrageApi.AddSeries(model.ProviderId, model.SeasonCount, model.SeasonList, qualityId, sickRageSettings.ApiKey, sickRageSettings.FullUri); Log.Trace("SickRage Add Result: "); diff --git a/PlexRequests.UI/Models/QualityModel.cs b/PlexRequests.UI/Models/QualityModel.cs new file mode 100644 index 000000000..80d7996b6 --- /dev/null +++ b/PlexRequests.UI/Models/QualityModel.cs @@ -0,0 +1,8 @@ +namespace PlexRequests.UI.Models +{ + public class QualityModel + { + public string Id { get; set; } + public string Name { get; set; } + } +} diff --git a/PlexRequests.UI/Models/RequestViewModel.cs b/PlexRequests.UI/Models/RequestViewModel.cs index 575681007..12f01f45b 100644 --- a/PlexRequests.UI/Models/RequestViewModel.cs +++ b/PlexRequests.UI/Models/RequestViewModel.cs @@ -52,5 +52,6 @@ namespace PlexRequests.UI.Models public string AdminNotes { get; set; } public string TvSeriesRequestType { get; set; } public string MusicBrainzId { get; set; } + public QualityModel[] Qualities { get; set; } } } diff --git a/PlexRequests.UI/Modules/ApprovalModule.cs b/PlexRequests.UI/Modules/ApprovalModule.cs index 64d861c96..cb2567109 100644 --- a/PlexRequests.UI/Modules/ApprovalModule.cs +++ b/PlexRequests.UI/Modules/ApprovalModule.cs @@ -59,7 +59,7 @@ namespace PlexRequests.UI.Modules SickRageApi = srApi; SickRageSettings = srSettings; - Post["/approve"] = parameters => Approve((int)Request.Form.requestid); + Post["/approve"] = parameters => Approve((int)Request.Form.requestid, (string)Request.Form.qualityId); Post["/approveall"] = x => ApproveAll(); Post["/approveallmovies"] = x => ApproveAllMovies(); Post["/approvealltvshows"] = x => ApproveAllTVShows(); @@ -80,7 +80,7 @@ namespace PlexRequests.UI.Modules /// /// The request identifier. /// - private Response Approve(int requestId) + private Response Approve(int requestId, string qualityId) { Log.Info("approving request {0}", requestId); if (!Context.CurrentUser.IsAuthenticated()) @@ -99,15 +99,15 @@ namespace PlexRequests.UI.Modules switch (request.Type) { case RequestType.Movie: - return RequestMovieAndUpdateStatus(request); + return RequestMovieAndUpdateStatus(request, qualityId); case RequestType.TvShow: - return RequestTvAndUpdateStatus(request); + return RequestTvAndUpdateStatus(request, qualityId); default: throw new ArgumentOutOfRangeException(nameof(request)); } } - private Response RequestTvAndUpdateStatus(RequestedModel request) + private Response RequestTvAndUpdateStatus(RequestedModel request, string qualityId) { var sender = new TvSender(SonarrApi, SickRageApi); @@ -115,7 +115,7 @@ namespace PlexRequests.UI.Modules if (sonarrSettings.Enabled) { Log.Trace("Sending to Sonarr"); - var result = sender.SendToSonarr(sonarrSettings, request); + var result = sender.SendToSonarr(sonarrSettings, request, qualityId); Log.Trace("Sonarr Result: "); Log.Trace(result.DumpJson()); if (!string.IsNullOrEmpty(result.title)) @@ -141,7 +141,7 @@ namespace PlexRequests.UI.Modules if (srSettings.Enabled) { Log.Trace("Sending to SickRage"); - var result = sender.SendToSickRage(srSettings, request); + var result = sender.SendToSickRage(srSettings, request, qualityId); Log.Trace("SickRage Result: "); Log.Trace(result.DumpJson()); if (result?.result == "success") @@ -169,7 +169,7 @@ namespace PlexRequests.UI.Modules }); } - private Response RequestMovieAndUpdateStatus(RequestedModel request) + private Response RequestMovieAndUpdateStatus(RequestedModel request, string qualityId) { var cpSettings = CpService.GetSettings(); var cp = new CouchPotatoApi(); @@ -190,7 +190,8 @@ namespace PlexRequests.UI.Modules Message = "We could not approve this request. Please try again or check the logs." }); } - var result = cp.AddMovie(request.ImdbId, cpSettings.ApiKey, request.Title, cpSettings.FullUri, cpSettings.ProfileId); + + var result = cp.AddMovie(request.ImdbId, cpSettings.ApiKey, request.Title, cpSettings.FullUri, string.IsNullOrEmpty(qualityId) ? cpSettings.ProfileId : qualityId); Log.Trace("Adding movie to CP result {0}", result); if (result) { diff --git a/PlexRequests.UI/Modules/RequestsModule.cs b/PlexRequests.UI/Modules/RequestsModule.cs index 7d7d7b8ad..ddeda5c34 100644 --- a/PlexRequests.UI/Modules/RequestsModule.cs +++ b/PlexRequests.UI/Modules/RequestsModule.cs @@ -41,17 +41,36 @@ using PlexRequests.Services.Notification; using PlexRequests.Store; using PlexRequests.UI.Models; using PlexRequests.Helpers; +using System.Collections.Generic; +using PlexRequests.Api.Interfaces; +using System.Threading.Tasks; namespace PlexRequests.UI.Modules { public class RequestsModule : BaseModule { - public RequestsModule(IRequestService service, ISettingsService prSettings, ISettingsService plex, INotificationService notify) : base("requests") + public RequestsModule( + IRequestService service, + ISettingsService prSettings, + ISettingsService plex, + INotificationService notify, + ISettingsService sonarrSettings, + ISettingsService sickRageSettings, + ISettingsService cpSettings, + ICouchPotatoApi cpApi, + ISonarrApi sonarrApi, + ISickRageApi sickRageApi) : base("requests") { Service = service; PrSettings = prSettings; PlexSettings = plex; NotificationService = notify; + SonarrSettings = sonarrSettings; + SickRageSettings = sickRageSettings; + CpSettings = cpSettings; + SonarrApi = sonarrApi; + SickRageApi = sickRageApi; + CpApi = cpApi; Get["/"] = _ => LoadRequests(); Get["/movies"] = _ => GetMovies(); @@ -71,6 +90,12 @@ namespace PlexRequests.UI.Modules private INotificationService NotificationService { get; } private ISettingsService PrSettings { get; } private ISettingsService PlexSettings { get; } + private ISettingsService SonarrSettings { get; } + private ISettingsService SickRageSettings { get; } + private ISettingsService CpSettings { get; } + private ISonarrApi SonarrApi { get; } + private ISickRageApi SickRageApi { get; } + private ICouchPotatoApi CpApi { get; } private Negotiator LoadRequests() { @@ -78,17 +103,51 @@ namespace PlexRequests.UI.Modules return View["Index", settings]; } - private Response GetMovies() + private Response GetMovies() // TODO: async await the API calls { var settings = PrSettings.GetSettings(); var isAdmin = Context.CurrentUser.IsAuthenticated(); - var dbMovies = Service.GetAll().Where(x => x.Type == RequestType.Movie); - if (settings.UsersCanViewOnlyOwnRequests && !isAdmin) + + List taskList = new List(); + + List dbMovies = new List(); + taskList.Add(Task.Factory.StartNew(() => + { + return Service.GetAll().Where(x => x.Type == RequestType.Movie); + + }).ContinueWith((t) => + { + dbMovies = t.Result.ToList(); + + if (settings.UsersCanViewOnlyOwnRequests && !isAdmin) + { + dbMovies = dbMovies.Where(x => x.UserHasRequested(Username)).ToList(); + } + })); + + + + List qualities = new List(); + + if (isAdmin) { - dbMovies = dbMovies.Where(x => x.UserHasRequested(Username)); + var cpSettings = CpSettings.GetSettings(); + if (cpSettings.Enabled) + { + taskList.Add(Task.Factory.StartNew(() => + { + return CpApi.GetProfiles(cpSettings.FullUri, cpSettings.ApiKey).list.Select(x => new QualityModel() { Id = x._id, Name = x.label }); // TODO: cache this! + }).ContinueWith((t) => + { + qualities = t.Result.ToList(); + })); + } } - var viewModel = dbMovies.Select(movie => { + Task.WaitAll(taskList.ToArray()); + + var viewModel = dbMovies.Select(movie => + { return new RequestViewModel { ProviderId = movie.ProviderId, @@ -111,23 +170,69 @@ namespace PlexRequests.UI.Modules Issues = movie.Issues.Humanize(LetterCasing.Title), OtherMessage = movie.OtherMessage, AdminNotes = movie.AdminNote, + Qualities = qualities.ToArray() }; }).ToList(); return Response.AsJson(viewModel); } - private Response GetTvShows() + private Response GetTvShows() // TODO: async await the API calls { var settings = PrSettings.GetSettings(); var isAdmin = Context.CurrentUser.IsAuthenticated(); - var dbTv = Service.GetAll().Where(x => x.Type == RequestType.TvShow); - if (settings.UsersCanViewOnlyOwnRequests && !isAdmin) + + List taskList = new List(); + + List dbTv = new List(); + taskList.Add(Task.Factory.StartNew(() => + { + return Service.GetAll().Where(x => x.Type == RequestType.TvShow); + + }).ContinueWith((t) => + { + dbTv = t.Result.ToList(); + + if (settings.UsersCanViewOnlyOwnRequests && !isAdmin) + { + dbTv = dbTv.Where(x => x.UserHasRequested(Username)).ToList(); + } + })); + + List qualities = new List(); + if (isAdmin) { - dbTv = dbTv.Where(x => x.UserHasRequested(Username)); + var sonarrSettings = SonarrSettings.GetSettings(); + if (sonarrSettings.Enabled) + { + taskList.Add(Task.Factory.StartNew(() => + { + return SonarrApi.GetProfiles(sonarrSettings.ApiKey, sonarrSettings.FullUri).Select(x => new QualityModel() { Id = x.id.ToString(), Name = x.name }); // TODO: cache this! + }).ContinueWith((t) => + { + qualities = t.Result.ToList(); + })); + } + else { + var sickRageSettings = SickRageSettings.GetSettings(); + if (sickRageSettings.Enabled) + { + taskList.Add(Task.Factory.StartNew(() => + { + return sickRageSettings.Qualities.Select(x => new QualityModel() { Id = x.Key, Name = x.Value }); // TODO: cache this! + }).ContinueWith((t) => + { + qualities = t.Result.ToList(); + })); + } + + } } - var viewModel = dbTv.Select(tv => { + Task.WaitAll(taskList.ToArray()); + + var viewModel = dbTv.Select(tv => + { return new RequestViewModel { ProviderId = tv.ProviderId, @@ -150,7 +255,8 @@ namespace PlexRequests.UI.Modules Issues = tv.Issues.Humanize(LetterCasing.Title), OtherMessage = tv.OtherMessage, AdminNotes = tv.AdminNote, - TvSeriesRequestType = tv.SeasonsRequested + TvSeriesRequestType = tv.SeasonsRequested, + Qualities = qualities.ToArray() }; }).ToList(); @@ -167,7 +273,8 @@ namespace PlexRequests.UI.Modules dbAlbum = dbAlbum.Where(x => x.UserHasRequested(Username)); } - var viewModel = dbAlbum.Select(album => { + var viewModel = dbAlbum.Select(album => + { return new RequestViewModel { ProviderId = album.ProviderId, diff --git a/PlexRequests.UI/PlexRequests.UI.csproj b/PlexRequests.UI/PlexRequests.UI.csproj index 6d08abb12..67e6a2e8a 100644 --- a/PlexRequests.UI/PlexRequests.UI.csproj +++ b/PlexRequests.UI/PlexRequests.UI.csproj @@ -171,6 +171,7 @@ + diff --git a/PlexRequests.UI/Views/Admin/Sickrage.cshtml b/PlexRequests.UI/Views/Admin/Sickrage.cshtml index 31e22d351..94cb51c6e 100644 --- a/PlexRequests.UI/Views/Admin/Sickrage.cshtml +++ b/PlexRequests.UI/Views/Admin/Sickrage.cshtml @@ -75,15 +75,10 @@
diff --git a/PlexRequests.UI/Views/Requests/Index.cshtml b/PlexRequests.UI/Views/Requests/Index.cshtml index e2b3d9bd6..16f332ecb 100644 --- a/PlexRequests.UI/Views/Requests/Index.cshtml +++ b/PlexRequests.UI/Views/Requests/Index.cshtml @@ -177,12 +177,27 @@ {{/if}} -
+
{{#if_eq admin true}} {{#if_eq approved false}}
- + {{#if_eq hasQualities true}} +
+ + + +
+ {{else}} + + {{/if_eq}}
{{/if_eq}}
diff --git a/PlexRequests.UI/Views/Search/Index.cshtml b/PlexRequests.UI/Views/Search/Index.cshtml index ef9145ee7..25aecb821 100644 --- a/PlexRequests.UI/Views/Search/Index.cshtml +++ b/PlexRequests.UI/Views/Search/Index.cshtml @@ -167,12 +167,12 @@