From 4808fffcef652890da3c1b7656b71b636ce43a43 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 7 Jun 2016 14:26:54 +0100 Subject: [PATCH] most of #273 done --- PlexRequests.Core/Models/IssuesModel.cs | 2 +- .../PlexRequests.UI.Tests.csproj | 1 + PlexRequests.UI.Tests/StringHelperTests.cs | 76 ++++++ PlexRequests.UI/Bootstrapper.cs | 6 +- PlexRequests.UI/Content/issues.js | 22 +- PlexRequests.UI/Content/search-1.7.js | 72 ++++++ PlexRequests.UI/Helpers/StringHelper.cs | 38 ++- PlexRequests.UI/Models/IssuesViewMOdel.cs | 2 +- PlexRequests.UI/Modules/IssuesModule.cs | 240 +++++++++++++++--- PlexRequests.UI/Modules/RequestsModule.cs | 2 +- PlexRequests.UI/Modules/SearchModule.cs | 4 +- PlexRequests.UI/Views/Issues/Details.cshtml | 9 +- PlexRequests.UI/Views/Issues/Index.cshtml | 26 +- PlexRequests.UI/Views/Requests/Index.cshtml | 5 - PlexRequests.UI/Views/Search/Index.cshtml | 49 +++- 15 files changed, 452 insertions(+), 102 deletions(-) create mode 100644 PlexRequests.UI.Tests/StringHelperTests.cs diff --git a/PlexRequests.Core/Models/IssuesModel.cs b/PlexRequests.Core/Models/IssuesModel.cs index 1460a4f6b..4aefb61cd 100644 --- a/PlexRequests.Core/Models/IssuesModel.cs +++ b/PlexRequests.Core/Models/IssuesModel.cs @@ -43,6 +43,7 @@ namespace PlexRequests.Core.Models public bool Deleted { get; set; } public RequestType Type { get; set; } public IssueStatus IssueStatus { get; set; } + public int ProviderId { get; set; } } public class IssueModel @@ -56,7 +57,6 @@ namespace PlexRequests.Core.Models public enum IssueStatus { PendingIssue, - InProgressIssue, ResolvedIssue } } \ No newline at end of file diff --git a/PlexRequests.UI.Tests/PlexRequests.UI.Tests.csproj b/PlexRequests.UI.Tests/PlexRequests.UI.Tests.csproj index 083fd2286..14096f6ff 100644 --- a/PlexRequests.UI.Tests/PlexRequests.UI.Tests.csproj +++ b/PlexRequests.UI.Tests/PlexRequests.UI.Tests.csproj @@ -102,6 +102,7 @@ + diff --git a/PlexRequests.UI.Tests/StringHelperTests.cs b/PlexRequests.UI.Tests/StringHelperTests.cs new file mode 100644 index 000000000..e1cbb811a --- /dev/null +++ b/PlexRequests.UI.Tests/StringHelperTests.cs @@ -0,0 +1,76 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: StringHelperTests.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.Collections.Generic; + +using NUnit.Framework; + +using PlexRequests.Core.Models; +using PlexRequests.UI.Helpers; + +namespace PlexRequests.UI.Tests +{ + [TestFixture] + public class StringHelperTests + { + [TestCaseSource(nameof(StringData))] + public string FirstCharToUpperTest(string input) + { + return input.FirstCharToUpper(); + } + + [TestCaseSource(nameof(StringCaseData))] + public string ToCamelCaseWordsTest(string input) + { + return input.ToCamelCaseWords(); + } + + private static IEnumerable StringData + { + get + { + yield return new TestCaseData("abcCba").Returns("AbcCba"); + yield return new TestCaseData("").Returns(""); + yield return new TestCaseData("12DSAda").Returns("12DSAda"); + } + } + + private static IEnumerable StringCaseData + { + get + { + yield return new TestCaseData("abcCba").Returns("Abc Cba"); + yield return new TestCaseData("").Returns(""); + yield return new TestCaseData("JamieRees").Returns("Jamie Rees"); + yield return new TestCaseData("Jamierees").Returns("Jamierees"); + yield return new TestCaseData("ThisIsANewString").Returns("This Is A New String"); + yield return new TestCaseData("").Returns(""); + yield return new TestCaseData(IssueStatus.PendingIssue.ToString()).Returns("Pending Issue"); + yield return new TestCaseData(IssueStatus.ResolvedIssue.ToString()).Returns("Resolved Issue"); + } + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Bootstrapper.cs b/PlexRequests.UI/Bootstrapper.cs index a85e03d78..74c577aba 100644 --- a/PlexRequests.UI/Bootstrapper.cs +++ b/PlexRequests.UI/Bootstrapper.cs @@ -111,11 +111,12 @@ namespace PlexRequests.UI container.Register(); container.Register(); + + container.AutoRegister(); + // Notification Service container.Register().AsSingleton(); - JsonSettings.MaxJsonLength = int.MaxValue; - SubscribeAllObservers(container); base.ConfigureRequestContainer(container, context); var loc = ServiceLocator.Instance; @@ -131,6 +132,7 @@ namespace PlexRequests.UI container.Register(); container.Register(); + JsonSettings.MaxJsonLength = int.MaxValue; CookieBasedSessions.Enable(pipelines, CryptographyConfiguration.Default); StaticConfiguration.DisableErrorTraces = false; diff --git a/PlexRequests.UI/Content/issues.js b/PlexRequests.UI/Content/issues.js index 70a081a65..f97ea0ba0 100644 --- a/PlexRequests.UI/Content/issues.js +++ b/PlexRequests.UI/Content/issues.js @@ -17,9 +17,6 @@ initLoad(); $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { var target = $(e.target).attr('href'); - if (target === "#inProgressTab") { - loadInProgressIssues(); - } if (target === "#resolvedTab") { loadResolvedIssues(); } @@ -117,10 +114,12 @@ $('#myModal').on('show.bs.modal', function (event) { var button = $(event.relatedTarget); // Button that triggered the modal var id = button.data('identifier'); // Extract info from data-* attributes + var modal = $(this); modal.find('.theSaveButton').val(id); // Add ID to the button var requestField = modal.find('input'); - requestField.val(id); // Add ID to the hidden field + requestField.val(id); // Add ID to the hidden field + }); // Update the note modal @@ -194,7 +193,7 @@ function initLoad() { } function loadCounts() { - var url = createBaseUrl(base, "issues/tabCount"); + var url = createBaseUrl(base, "/issues/tabCount"); $.ajax({ type: "get", url: url, @@ -226,13 +225,6 @@ function loadPendingIssues() { loadIssues("pending", $('#pendingIssues')); } - -function loadInProgressIssues() { - var $element = $('#inprogressIssues'); - $element.html(""); - loadIssues("inprogress", $element); -} - function loadResolvedIssues() { var $element = $('#resolvedIssues'); $element.html(""); @@ -240,8 +232,8 @@ function loadResolvedIssues() { } function loadIssues(type, element) { - var url = createBaseUrl(base, "issues/" + type); - var linkUrl = createBaseUrl(base, "issues/"); + var url = createBaseUrl(base, "/issues/" + type); + var linkUrl = createBaseUrl(base, "/issues/"); $.ajax({ type: "get", url: url, @@ -272,7 +264,7 @@ function buildIssueContext(result) { requestId: result.requestId, type: result.type, title: result.title, - count: result.count + issues: result.issues }; return context; diff --git a/PlexRequests.UI/Content/search-1.7.js b/PlexRequests.UI/Content/search-1.7.js index 96e6a3bd0..2baa49750 100644 --- a/PlexRequests.UI/Content/search-1.7.js +++ b/PlexRequests.UI/Content/search-1.7.js @@ -184,6 +184,78 @@ $(function () { }); }); + // Report Issue + $(document).on("click", ".dropdownIssue", function (e) { + var issue = $(this).attr("issue-select"); + var id = e.target.id; + // Other issue so the modal is opening + if (issue == 4) { + return; + } + e.preventDefault(); + + var $form = $('#report' + id); + var data = $form.serialize(); + data = data + "&issue=" + issue; + + $.ajax({ + type: $form.prop('method'), + url: $form.prop('action'), + data: data, + dataType: "json", + success: function (response) { + if (checkJsonResponse(response)) { + generateNotify("Successfully Reported Issue.", "success"); + } + }, + error: function (e) { + console.log(e); + generateNotify("Something went wrong!", "danger"); + } + }); + }); + + // Save Modal click + $(".theSaveButton").click(function (e) { + var comment = $("#commentArea").val(); + e.preventDefault(); + + var $form = $("#commentForm"); + var data = $form.serialize(); + data = data + "&comment=" + comment; + + $.ajax({ + type: $form.prop("method"), + url: $form.prop("action"), + data: data, + dataType: "json", + success: function (response) { + if (checkJsonResponse(response)) { + generateNotify("Success! Added Issue.", "success"); + $("#myModal").modal("hide"); + } + }, + error: function (e) { + console.log(e); + generateNotify("Something went wrong!", "danger"); + } + }); + }); + + // Update the modal + $('#issuesModal').on('show.bs.modal', function (event) { + var button = $(event.relatedTarget); // Button that triggered the modal + var id = button.data('identifier'); // Extract info from data-* attributes + var type = button.data('type'); // Extract info from data-* attributes + + var modal = $(this); + modal.find('.theSaveButton').val(id); // Add ID to the button + + + $('#providerIdModal').val(id); + $('#typeModal').val(type); + }); + function focusSearch($content) { if ($content.length > 0) { $('input[type=text].form-control', $content).first().focus(); diff --git a/PlexRequests.UI/Helpers/StringHelper.cs b/PlexRequests.UI/Helpers/StringHelper.cs index e1368bb64..421ddb9ae 100644 --- a/PlexRequests.UI/Helpers/StringHelper.cs +++ b/PlexRequests.UI/Helpers/StringHelper.cs @@ -1,4 +1,29 @@ -using System; +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: StringHelper.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.Linq; using System.Text.RegularExpressions; @@ -8,15 +33,18 @@ namespace PlexRequests.UI.Helpers { public static string FirstCharToUpper(this string input) { - if (String.IsNullOrEmpty(input)) + if (string.IsNullOrEmpty(input)) return input; - return input.First().ToString().ToUpper() + String.Join("", input.Skip(1)); + var firstUpper = char.ToUpper(input[0]); + return firstUpper + string.Join("", input.Skip(1)); } - public static string CamelCaseToWords(this string input) + public static string ToCamelCaseWords(this string input) { + if (string.IsNullOrEmpty(input)) + return input; return Regex.Replace(input.FirstCharToUpper(), "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))", "$1 "); } } -} +} \ No newline at end of file diff --git a/PlexRequests.UI/Models/IssuesViewMOdel.cs b/PlexRequests.UI/Models/IssuesViewMOdel.cs index e26eb26c3..d05b2a8e8 100644 --- a/PlexRequests.UI/Models/IssuesViewMOdel.cs +++ b/PlexRequests.UI/Models/IssuesViewMOdel.cs @@ -34,7 +34,7 @@ namespace PlexRequests.UI.Models public int Id { get; set; } public int RequestId { get; set; } public string Title { get; set; } - public int Count { get; set; } + public string Issues { get; set; } public string Type { get; set; } } diff --git a/PlexRequests.UI/Modules/IssuesModule.cs b/PlexRequests.UI/Modules/IssuesModule.cs index ee835bbd4..db0b9742b 100644 --- a/PlexRequests.UI/Modules/IssuesModule.cs +++ b/PlexRequests.UI/Modules/IssuesModule.cs @@ -10,10 +10,13 @@ using Nancy.Security; using NLog; +using PlexRequests.Api; using PlexRequests.Core; using PlexRequests.Core.Models; using PlexRequests.Core.SettingModels; using PlexRequests.Helpers; +using PlexRequests.Services.Interfaces; +using PlexRequests.Services.Notification; using PlexRequests.Store; using PlexRequests.UI.Helpers; using PlexRequests.UI.Models; @@ -22,31 +25,34 @@ namespace PlexRequests.UI.Modules { public class IssuesModule : BaseAuthModule { - public IssuesModule(ISettingsService pr, IIssueService issueService, IRequestService request) : base("issues", pr) + public IssuesModule(ISettingsService pr, IIssueService issueService, IRequestService request, INotificationService n) : base("issues", pr) { IssuesService = issueService; RequestService = request; + NotificationService = n; Get["/"] = x => Index(); Get["/{id}", true] = async (x, ct) => await Details(x.id); - Post["/issue", true] = async (x, ct) => await ReportIssue((int)Request.Form.requestId, (IssueState)(int)Request.Form.issue, null); + Post["/issue", true] = async (x, ct) => await ReportRequestIssue((int)Request.Form.requestId, (IssueState)(int)Request.Form.issue, null); - Get["/inprogress", true] = async (x, ct) => await GetIssues(IssueStatus.InProgressIssue); Get["/pending", true] = async (x, ct) => await GetIssues(IssueStatus.PendingIssue); Get["/resolved", true] = async (x, ct) => await GetIssues(IssueStatus.ResolvedIssue); Post["/remove", true] = async (x, ct) => await RemoveIssue((int)Request.Form.issueId); - Post["/inprogressUpdate", true] = async (x, ct) => await ChangeStatus((int)Request.Form.issueId, IssueStatus.InProgressIssue); Post["/resolvedUpdate", true] = async (x, ct) => await ChangeStatus((int)Request.Form.issueId, IssueStatus.ResolvedIssue); - Post["/clear", true] = async (x, ct) => await ClearIssue((int) Request.Form.issueId, (IssueState) (int) Request.Form.issue); + Post["/clear", true] = async (x, ct) => await ClearIssue((int)Request.Form.issueId, (IssueState)(int)Request.Form.issue); Get["/issuecount", true] = async (x, ct) => await IssueCount(); Get["/tabCount", true] = async (x, ct) => await TabCount(); - Post["/issuecomment", true] = async (x, ct) => await ReportIssue((int)Request.Form.requestId, IssueState.Other, (string)Request.Form.commentArea); + Post["/issuecomment", true] = async (x, ct) => await ReportRequestIssue((int)Request.Form.provierId, IssueState.Other, (string)Request.Form.commentArea); + + Post["/nonrequestissue", true] = async (x, ct) => await ReportNonRequestIssue((int)Request.Form.providerId, (string)Request.Form.type, (IssueState)(int)Request.Form.issue, null); + + Post["/nonrequestissuecomment", true] = async (x, ct) => await ReportNonRequestIssue((int)Request.Form.providerId, (string)Request.Form.type, IssueState.Other, (string)Request.Form.commentArea); Post["/addnote", true] = async (x, ct) => await AddNote((int)Request.Form.requestId, (string)Request.Form.noteArea, (IssueState)(int)Request.Form.issue); @@ -54,6 +60,7 @@ namespace PlexRequests.UI.Modules private IIssueService IssuesService { get; } private IRequestService RequestService { get; } + private INotificationService NotificationService { get; } private static Logger Log = LogManager.GetCurrentClassLogger(); public Negotiator Index() @@ -64,22 +71,43 @@ namespace PlexRequests.UI.Modules private async Task GetIssues(IssueStatus status) { var issues = await IssuesService.GetAllAsync(); - issues = await FilterIssues(issues); + issues = await FilterIssuesAsync(issues, status == IssueStatus.ResolvedIssue); var issuesModels = issues as IssuesModel[] ?? issues.Where(x => x.IssueStatus == status).ToArray(); - var model = issuesModels.Select(i => new IssuesViewModel + var viewModel = new List(); + + foreach (var i in issuesModels) { - Title = i.Title, Type = i.Type.ToString().CamelCaseToWords(), Count = i.Issues.Count, Id = i.Id, RequestId = i.RequestId - }).ToList(); + var model = new IssuesViewModel { Id = i.Id, RequestId = i.RequestId, Title = i.Title, Type = i.Type.ToString().ToCamelCaseWords(), }; + + // Create a string with all of the current issue states with a "," delimiter in e.g. Wrong Content, Playback Issues + var state = i.Issues.Select(x => x.Issue).ToArray(); + var issueState = string.Empty; + for (var j = 0; j < state.Length; j++) + { + var word = state[j].ToString().ToCamelCaseWords(); + if (j != state.Length - 1) + { + issueState += $"{word}, "; + } + else + { + issueState += word; + } + } + model.Issues = issueState; + + viewModel.Add(model); + } - return Response.AsJson(model); + return Response.AsJson(viewModel); } public async Task IssueCount() { var issues = await IssuesService.GetAllAsync(); - var myIssues = await FilterIssues(issues); + var myIssues = await FilterIssuesAsync(issues); var count = myIssues.Count(); @@ -90,19 +118,17 @@ namespace PlexRequests.UI.Modules { var issues = await IssuesService.GetAllAsync(); - var myIssues = await FilterIssues(issues); + var myIssues = await FilterIssuesAsync(issues); var count = new List(); var issuesModels = myIssues as IssuesModel[] ?? myIssues.ToArray(); var pending = issuesModels.Where(x => x.IssueStatus == IssueStatus.PendingIssue); - var progress = issuesModels.Where(x => x.IssueStatus == IssueStatus.InProgressIssue); var resolved = issuesModels.Where(x => x.IssueStatus == IssueStatus.ResolvedIssue); - - count.Add(new { Name = IssueStatus.PendingIssue, Count = pending.Count()}); - count.Add(new { Name = IssueStatus.InProgressIssue, Count = progress.Count()}); - count.Add(new { Name = IssueStatus.ResolvedIssue, Count = resolved.Count()}); - + + count.Add(new { Name = IssueStatus.PendingIssue, Count = pending.Count() }); + count.Add(new { Name = IssueStatus.ResolvedIssue, Count = resolved.Count() }); + return Response.AsJson(count); } @@ -115,7 +141,7 @@ namespace PlexRequests.UI.Modules : View["Details", issue]; } - private async Task ReportIssue(int requestId, IssueState issue, string comment) + private async Task ReportRequestIssue(int requestId, IssueState issue, string comment) { var model = new IssueModel @@ -132,13 +158,22 @@ namespace PlexRequests.UI.Modules var issueEntity = await IssuesService.GetAllAsync(); var existingIssue = issueEntity.FirstOrDefault(x => x.RequestId == requestId); + var notifyModel = new NotificationModel + { + User = Username, + NotificationType = NotificationType.Issue, + Title = request.Title, + DateTime = DateTime.Now, + Body = issue == IssueState.Other ? comment : issue.ToString().ToCamelCaseWords() + }; + // An issue already exists if (existingIssue != null) { if (existingIssue.Issues.Any(x => x.Issue == issue)) { return - Response.AsJson(new JsonResponseModel() + Response.AsJson(new JsonResponseModel { Result = false, Message = "This issue has already been reported!" @@ -148,6 +183,9 @@ namespace PlexRequests.UI.Modules existingIssue.Issues.Add(model); var result = await IssuesService.UpdateIssueAsync(existingIssue); + + await NotificationService.Publish(notifyModel); + return Response.AsJson(result ? new JsonResponseModel { Result = true } : new JsonResponseModel { Result = false }); @@ -169,28 +207,144 @@ namespace PlexRequests.UI.Modules request.IssueId = issueId; await RequestService.UpdateRequestAsync(request); + await NotificationService.Publish(notifyModel); + return Response.AsJson(new JsonResponseModel { Result = true }); + } + + private async Task ReportNonRequestIssue(int providerId, string type, IssueState issue, string comment) + { + var currentIssues = await IssuesService.GetAllAsync(); + var notifyModel = new NotificationModel + { + User = Username, + NotificationType = NotificationType.Issue, + DateTime = DateTime.Now, + Body = issue == IssueState.Other ? comment : issue.ToString().ToCamelCaseWords() + }; + var model = new IssueModel + { + Issue = issue, + UserReported = Username, + UserNote = !string.IsNullOrEmpty(comment) + ? $"{Username} - {comment}" + : string.Empty, + }; + + var existing = currentIssues.FirstOrDefault(x => x.ProviderId == providerId && !x.Deleted && x.IssueStatus == IssueStatus.PendingIssue); + if (existing != null) + { + existing.Issues.Add(model); + await IssuesService.UpdateIssueAsync(existing); + return Response.AsJson(new JsonResponseModel { Result = true }); + } + + if (type == "movie") + { + var movieApi = new TheMovieDbApi(); + + var result = await movieApi.GetMovieInformation(providerId); + if (result != null) + { + notifyModel.Title = result.Title; + // New issue + var issues = new IssuesModel + { + Title = result.Title, + PosterUrl = "https://image.tmdb.org/t/p/w150/" + result.PosterPath, + ProviderId = providerId, + Type = RequestType.Movie, + IssueStatus = IssueStatus.PendingIssue + }; + issues.Issues.Add(model); + + var issueId = await IssuesService.AddIssueAsync(issues); + + await NotificationService.Publish(notifyModel); + return Response.AsJson(new JsonResponseModel { Result = true }); + } + } + + if (type == "tv") + { + var tv = new TvMazeApi(); + var result = tv.ShowLookupByTheTvDbId(providerId); + if (result != null) + { + var banner = result.image?.medium; + if (!string.IsNullOrEmpty(banner)) + { + banner = banner.Replace("http", "https"); + } + + notifyModel.Title = result.name; + // New issue + var issues = new IssuesModel + { + Title = result.name, + PosterUrl = banner, + ProviderId = providerId, + Type = RequestType.TvShow, + IssueStatus = IssueStatus.PendingIssue + }; + issues.Issues.Add(model); + + var issueId = await IssuesService.AddIssueAsync(issues); + + await NotificationService.Publish(notifyModel); + return Response.AsJson(new JsonResponseModel { Result = true }); + } + } + + return Response.AsJson(new JsonResponseModel { Result = true }); } - private async Task> FilterIssues(IEnumerable issues) + /// + /// Filters the issues. Checks to see if we have set UsersCanViewOnlyOwnIssues in the database and filters upon the user logged in and that setting. + /// + /// The issues. + private async Task> FilterIssuesAsync(IEnumerable issues, bool showResolved = false) { var settings = await PlexRequestSettings.GetSettingsAsync(); IEnumerable myIssues; + + // Is the user an Admin? If so show everything if (IsAdmin) { - myIssues = issues.Where(x => x.Deleted == false); + var issuesModels = issues as IssuesModel[] ?? issues.ToArray(); + myIssues = issuesModels.Where(x => x.Deleted == false); + if (!showResolved) + { + myIssues = issuesModels.Where(x => x.IssueStatus != IssueStatus.ResolvedIssue); + } } - else if (settings.UsersCanViewOnlyOwnIssues) + else if (settings.UsersCanViewOnlyOwnIssues) // The user is not an Admin, do we have the settings to hide them? { - myIssues = - issues.Where( - x => - x.Issues.Any(i => i.UserReported.Equals(Username, StringComparison.CurrentCultureIgnoreCase)) && x.Deleted == false); + if (!showResolved) + { + myIssues = + issues.Where( + x => + x.Issues.Any(i => i.UserReported.Equals(Username, StringComparison.CurrentCultureIgnoreCase)) && x.Deleted == false + && x.IssueStatus != IssueStatus.ResolvedIssue); + } + else + { + myIssues = + issues.Where( + x => + x.Issues.Any(i => i.UserReported.Equals(Username, StringComparison.CurrentCultureIgnoreCase)) && x.Deleted == false); + } } - else + else // Looks like the user is not an admin and there is no settings set. { - myIssues = issues.Where(x => x.Deleted == false); + var issuesModels = issues as IssuesModel[] ?? issues.ToArray(); + myIssues = issuesModels.Where(x => x.Deleted == false); + if (!showResolved) + { + myIssues = issuesModels.Where(x => x.IssueStatus != IssueStatus.ResolvedIssue); + } } return myIssues; @@ -200,10 +354,19 @@ namespace PlexRequests.UI.Modules try { this.RequiresClaims(UserClaims.Admin); + var issue = await IssuesService.GetAsync(issueId); + var request = await RequestService.GetAsync(issue.RequestId); + + request.IssueId = 0; // No issue; - await IssuesService.DeleteIssueAsync(issueId); + var result = await RequestService.UpdateRequestAsync(request); + if (result) + { + await IssuesService.DeleteIssueAsync(issueId); + } return View["Index"]; + } catch (Exception e) { @@ -256,10 +419,12 @@ namespace PlexRequests.UI.Modules } var toAddNote = issue.Issues.FirstOrDefault(x => x.Issue == state); - issue.Issues.Remove(toAddNote); - toAddNote.AdminNote = noteArea; - issue.Issues.Add(toAddNote); - + if (toAddNote != null) + { + issue.Issues.Remove(toAddNote); + toAddNote.AdminNote = noteArea; + issue.Issues.Add(toAddNote); + } var result = await IssuesService.UpdateIssueAsync(issue); return Response.AsJson(result @@ -267,6 +432,11 @@ namespace PlexRequests.UI.Modules : new JsonResponseModel { Result = false, Message = "Could not update the notes, please try again or check the logs" }); } + /// + /// Orders the issues descending by the . + /// + /// The issues. + /// private IssuesModel Order(IssuesModel issues) { issues.Issues = issues.Issues.OrderByDescending(x => x.Issue).ToList(); diff --git a/PlexRequests.UI/Modules/RequestsModule.cs b/PlexRequests.UI/Modules/RequestsModule.cs index 2f2ff60e5..03ef43ece 100644 --- a/PlexRequests.UI/Modules/RequestsModule.cs +++ b/PlexRequests.UI/Modules/RequestsModule.cs @@ -328,7 +328,7 @@ namespace PlexRequests.UI.Modules NotificationType = NotificationType.Issue, Title = originalRequest.Title, DateTime = DateTime.Now, - Body = issue == IssueState.Other ? comment : issue.ToString().CamelCaseToWords() + Body = issue == IssueState.Other ? comment : issue.ToString().ToCamelCaseWords() }; await NotificationService.Publish(model); diff --git a/PlexRequests.UI/Modules/SearchModule.cs b/PlexRequests.UI/Modules/SearchModule.cs index c6bd8b748..2a4bbc719 100644 --- a/PlexRequests.UI/Modules/SearchModule.cs +++ b/PlexRequests.UI/Modules/SearchModule.cs @@ -408,11 +408,9 @@ namespace PlexRequests.UI.Modules private async Task RequestMovie(int movieId) { - var movieApi = new TheMovieDbApi(); - var movieInfo = movieApi.GetMovieInformation(movieId).Result; + var movieInfo = MovieApi.GetMovieInformation(movieId).Result; var fullMovieName = $"{movieInfo.Title}{(movieInfo.ReleaseDate.HasValue ? $" ({movieInfo.ReleaseDate.Value.Year})" : string.Empty)}"; Log.Trace("Getting movie info from TheMovieDb"); - //#if !DEBUG var settings = await PrService.GetSettingsAsync(); diff --git a/PlexRequests.UI/Views/Issues/Details.cshtml b/PlexRequests.UI/Views/Issues/Details.cshtml index eb69a04d0..971a43fbf 100644 --- a/PlexRequests.UI/Views/Issues/Details.cshtml +++ b/PlexRequests.UI/Views/Issues/Details.cshtml @@ -34,13 +34,6 @@
@if (Model.IssueStatus == IssueStatus.PendingIssue) - { -
- - -
- } - @if (Model.IssueStatus == IssueStatus.InProgressIssue) {
@@ -67,7 +60,7 @@ {
-
Type: @StringHelper.CamelCaseToWords(issue.Issue.ToString())
+
Type: @StringHelper.ToCamelCaseWords(issue.Issue.ToString())
User Reported: @issue.UserReported
User Note: @issue.UserNote
Admin Note:@issue.AdminNote
diff --git a/PlexRequests.UI/Views/Issues/Index.cshtml b/PlexRequests.UI/Views/Issues/Index.cshtml index 38a7fe5b7..40223f0f4 100644 --- a/PlexRequests.UI/Views/Issues/Index.cshtml +++ b/PlexRequests.UI/Views/Issues/Index.cshtml @@ -6,11 +6,10 @@
-
+

Title

@@ -18,18 +17,18 @@

Type

-
+

Issue's

Requested

-
+
- +
@@ -41,17 +40,6 @@
- -
- -
-
- -
- -
-
-
@@ -73,8 +61,8 @@
{{type}}
-
- Issues: {{count}} +
+ {{issues}}
@@ -84,7 +72,7 @@
{{/if}}
- diff --git a/PlexRequests.UI/Views/Requests/Index.cshtml b/PlexRequests.UI/Views/Requests/Index.cshtml index 66073161b..95db35a11 100644 --- a/PlexRequests.UI/Views/Requests/Index.cshtml +++ b/PlexRequests.UI/Views/Requests/Index.cshtml @@ -215,11 +215,6 @@ -
- - -
-
{{#if_eq available true}} diff --git a/PlexRequests.UI/Views/Search/Index.cshtml b/PlexRequests.UI/Views/Search/Index.cshtml index a34bec151..5e6d01085 100644 --- a/PlexRequests.UI/Views/Search/Index.cshtml +++ b/PlexRequests.UI/Views/Search/Index.cshtml @@ -196,14 +196,25 @@ {{/if_eq}} {{/if_eq}} {{/if_eq}} -
-
-
- {{#if voteAverage}} - Vote Average: {{voteAverage}} - Vote Count: {{voteCount}} - {{/if}} +
+
+
+ + +
@@ -277,6 +288,30 @@
+ + +