diff --git a/PlexRequests.Core/SettingModels/PlexRequestSettings.cs b/PlexRequests.Core/SettingModels/PlexRequestSettings.cs index dc27da865..20bf58acd 100644 --- a/PlexRequests.Core/SettingModels/PlexRequestSettings.cs +++ b/PlexRequests.Core/SettingModels/PlexRequestSettings.cs @@ -41,6 +41,7 @@ namespace PlexRequests.Core.SettingModels public bool RequireTvShowApproval { get; set; } public bool RequireMusicApproval { get; set; } public bool UsersCanViewOnlyOwnRequests { get; set; } + public bool UsersCanViewOnlyOwnIssues { get; set; } public int WeeklyRequestLimit { get; set; } public string NoApprovalUsers { get; set; } diff --git a/PlexRequests.UI/Content/Themes/plex.css b/PlexRequests.UI/Content/Themes/plex.css index c0a7597af..7444041c8 100644 --- a/PlexRequests.UI/Content/Themes/plex.css +++ b/PlexRequests.UI/Content/Themes/plex.css @@ -156,3 +156,17 @@ button.list-group-item:focus { background-clip: padding-box; outline: 0; } +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: 300; + color: #ebebeb; + line-height: 1; + vertical-align: middle; + white-space: nowrap; + text-align: center; + background-color: #333333; + border-radius: 10px; } + diff --git a/PlexRequests.UI/Content/Themes/plex.min.css b/PlexRequests.UI/Content/Themes/plex.min.css index 2fa5bbcc9..20a9bff7b 100644 --- a/PlexRequests.UI/Content/Themes/plex.min.css +++ b/PlexRequests.UI/Content/Themes/plex.min.css @@ -1 +1 @@ -.form-control-custom{background-color:#333 !important;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background:#df691a;}scroll-top-wrapper{background-color:#333;}.scroll-top-wrapper:hover{background-color:#df691a;}body{font-family:Open Sans Regular,Helvetica Neue,Helvetica,Arial,sans-serif;color:#eee;background-color:#1f1f1f;}.table-striped>tbody>tr:nth-of-type(odd){background-color:#333;}.table-hover>tbody>tr:hover{background-color:#282828;}fieldset{padding:15px;}legend{border-bottom:1px solid #333;}.form-control{color:#fefefe;background-color:#333;}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{margin-left:-0;}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:-15px;}.dropdown-menu{background-color:#282828;}.dropdown-menu .divider{background-color:#333;}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#333;}.input-group-addon{background-color:#333;}.nav>li>a:hover,.nav>li>a:focus{background-color:#df691a;}.nav-tabs>li>a:hover{border-color:#df691a #df691a transparent;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background-color:#df691a;border:1px solid #df691a;}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #df691a;}.navbar-default{background-color:#0a0a0a;}.navbar-default .navbar-brand{color:#df691a;}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#f0ad4e;background-color:#282828;}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{background-color:#282828;}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#df691a;color:#fff;}.pagination>li>a,.pagination>li>span{background-color:#282828;}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#333;}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#fefefe;background-color:#333;}.list-group-item{background-color:#282828;}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{background-color:#333;}.input-addon,.input-group-addon{color:#df691a;}.modal-header,.modal-footer{background-color:#282828;}.modal-content{position:relative;background-color:#282828;border:1px solid transparent;border-radius:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;outline:0;} \ No newline at end of file +.form-control-custom{background-color:#333 !important;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background:#df691a;}scroll-top-wrapper{background-color:#333;}.scroll-top-wrapper:hover{background-color:#df691a;}body{font-family:Open Sans Regular,Helvetica Neue,Helvetica,Arial,sans-serif;color:#eee;background-color:#1f1f1f;}.table-striped>tbody>tr:nth-of-type(odd){background-color:#333;}.table-hover>tbody>tr:hover{background-color:#282828;}fieldset{padding:15px;}legend{border-bottom:1px solid #333;}.form-control{color:#fefefe;background-color:#333;}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{margin-left:-0;}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:-15px;}.dropdown-menu{background-color:#282828;}.dropdown-menu .divider{background-color:#333;}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#333;}.input-group-addon{background-color:#333;}.nav>li>a:hover,.nav>li>a:focus{background-color:#df691a;}.nav-tabs>li>a:hover{border-color:#df691a #df691a transparent;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background-color:#df691a;border:1px solid #df691a;}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #df691a;}.navbar-default{background-color:#0a0a0a;}.navbar-default .navbar-brand{color:#df691a;}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#f0ad4e;background-color:#282828;}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{background-color:#282828;}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#df691a;color:#fff;}.pagination>li>a,.pagination>li>span{background-color:#282828;}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#333;}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#fefefe;background-color:#333;}.list-group-item{background-color:#282828;}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{background-color:#333;}.input-addon,.input-group-addon{color:#df691a;}.modal-header,.modal-footer{background-color:#282828;}.modal-content{position:relative;background-color:#282828;border:1px solid transparent;border-radius:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;outline:0;}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:300;color:#ebebeb;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#333;border-radius:10px;} \ No newline at end of file diff --git a/PlexRequests.UI/Content/Themes/plex.scss b/PlexRequests.UI/Content/Themes/plex.scss index 1de0e2092..ba48f2d20 100644 --- a/PlexRequests.UI/Content/Themes/plex.scss +++ b/PlexRequests.UI/Content/Themes/plex.scss @@ -194,3 +194,18 @@ button.list-group-item:focus { background-clip: padding-box; outline: 0; } + +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: 300; + color: #ebebeb; + line-height: 1; + vertical-align: middle; + white-space: nowrap; + text-align: center; + background-color: $bg-colour; + border-radius: 10px; +} \ No newline at end of file diff --git a/PlexRequests.UI/Content/issue-details.js b/PlexRequests.UI/Content/issue-details.js new file mode 100644 index 000000000..28b10c997 --- /dev/null +++ b/PlexRequests.UI/Content/issue-details.js @@ -0,0 +1,46 @@ +var base = $('#baseUrl').text(); + + +// Note Modal click +$(".theNoteSaveButton").click(function (e) { + var comment = $("#noteArea").val(); + e.preventDefault(); + + var $form = $("#noteForm"); + var data = $form.serialize(); + + + $.ajax({ + type: $form.prop("method"), + url: $form.prop("action"), + data: data, + dataType: "json", + success: function (response) { + if (checkJsonResponse(response)) { + location.reload(); + } + }, + error: function (e) { + console.log(e); + generateNotify("Something went wrong!", "danger"); + } + }); +}); +// Update the note modal +$('#noteModal').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 issue = button.data('issue'); + var modal = $(this); + modal.find('.theNoteSaveButton').val(id); // Add ID to the button + var requestField = modal.find('.noteId'); + requestField.val(id); // Add ID to the hidden field + var noteType = modal.find('.issue'); + noteType.val(issue); + + }); + + + + + diff --git a/PlexRequests.UI/Content/issues.js b/PlexRequests.UI/Content/issues.js index 74d0afda3..70a081a65 100644 --- a/PlexRequests.UI/Content/issues.js +++ b/PlexRequests.UI/Content/issues.js @@ -14,6 +14,16 @@ var base = $('#baseUrl').text(); 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(); + } +}); // Report Issue @@ -179,14 +189,58 @@ $(document).on("click", ".clear", function (e) { function initLoad() { + loadCounts(); loadPendingIssues(); - } +function loadCounts() { + var url = createBaseUrl(base, "issues/tabCount"); + $.ajax({ + type: "get", + url: url, + dataType: "json", + success: function (response) { + if (response.length > 0) { + response.forEach(function (result) { + if (result.count > 0) { + + if (result.name == 0) { + $('#pendingCount').addClass("badge"); + $('#pendingCount').html(result.count); + } else if (result.name == 1) { + $('#inProgressCount').addClass("badge"); + $('#inProgressCount').html(result.count); + } else if (result.name == 2) { + $('#resolvedCount').addClass("badge"); + $('#resolvedCount').html(result.count); + } + + } + }); + }; + } + }); +} function loadPendingIssues() { - $issues = $('#pendingIssues'); - var url = createBaseUrl(base, "issues/pending"); + loadIssues("pending", $('#pendingIssues')); +} + + +function loadInProgressIssues() { + var $element = $('#inprogressIssues'); + $element.html(""); + loadIssues("inprogress", $element); +} + +function loadResolvedIssues() { + var $element = $('#resolvedIssues'); + $element.html(""); + loadIssues("resolved", $element); +} + +function loadIssues(type, element) { + var url = createBaseUrl(base, "issues/" + type); var linkUrl = createBaseUrl(base, "issues/"); $.ajax({ type: "get", @@ -194,12 +248,12 @@ function loadPendingIssues() { dataType: "json", success: function (response) { if (response.length > 0) { - response.forEach(function(result) { + response.forEach(function (result) { var context = buildIssueContext(result); var html = issueTemplate(context); - $issues.append(html); + element.append(html); - $("#" +result.id + "link").attr("href", linkUrl + result.id); + $("#" + result.id + "link").attr("href", linkUrl + result.id); }); }; }, @@ -208,7 +262,6 @@ function loadPendingIssues() { generateNotify("Could not load Pending issues", "danger"); } }); - } diff --git a/PlexRequests.UI/Content/requests-1.7.js b/PlexRequests.UI/Content/requests-1.7.js index f7c7aff42..041b67bcc 100644 --- a/PlexRequests.UI/Content/requests-1.7.js +++ b/PlexRequests.UI/Content/requests-1.7.js @@ -445,31 +445,6 @@ $(document).on("click", ".approve-with-quality", function (e) { }); -// Clear issues -$(document).on("click", ".clear", function (e) { - e.preventDefault(); - var buttonId = e.target.id; - var $form = $('#clear' + buttonId); - - $.ajax({ - type: $form.prop('method'), - url: $form.prop('action'), - data: $form.serialize(), - dataType: "json", - success: function (response) { - - if (checkJsonResponse(response)) { - generateNotify("Success! Issues Cleared.", "info"); - $('#issueArea' + buttonId).html("
Issue: None
"); - } - }, - error: function (e) { - console.log(e); - generateNotify("Something went wrong!", "danger"); - } - }); - -}); // Change Availability $(document).on("click", ".change", function (e) { diff --git a/PlexRequests.UI/Content/site-1.7.js b/PlexRequests.UI/Content/site-1.7.js index 4887b10b0..53bec3d7f 100644 --- a/PlexRequests.UI/Content/site-1.7.js +++ b/PlexRequests.UI/Content/site-1.7.js @@ -45,7 +45,7 @@ function loadingButton(elementId, originalCss) { $element.removeClass("btn-" + originalCss + "-outline").addClass("btn-primary-outline").addClass('disabled').html(" Loading..."); // handle split-buttons - var $dropdown = $element.next('.dropdown-toggle') + var $dropdown = $element.next('.dropdown-toggle'); if ($dropdown.length > 0) { $dropdown.removeClass("btn-" + originalCss + "-outline").addClass("btn-primary-outline").addClass('disabled'); } @@ -56,7 +56,7 @@ function finishLoading(elementId, originalCss, html) { $element.removeClass("btn-primary-outline").removeClass('disabled').addClass("btn-" + originalCss + "-outline").html(html); // handle split-buttons - var $dropdown = $element.next('.dropdown-toggle') + var $dropdown = $element.next('.dropdown-toggle'); if ($dropdown.length > 0) { $dropdown.removeClass("btn-primary-outline").removeClass('disabled').addClass("btn-" + originalCss + "-outline"); } diff --git a/PlexRequests.UI/Helpers/BaseUrlHelper.cs b/PlexRequests.UI/Helpers/BaseUrlHelper.cs index 12b6fcca3..2d3f0ad22 100644 --- a/PlexRequests.UI/Helpers/BaseUrlHelper.cs +++ b/PlexRequests.UI/Helpers/BaseUrlHelper.cs @@ -113,6 +113,18 @@ namespace PlexRequests.UI.Helpers sb.AppendLine($""); + return helper.Raw(sb.ToString()); + } + + public static IHtmlString LoadIssueDetailsAssets(this HtmlHelpers helper) + { + var sb = new StringBuilder(); + var assetLocation = GetBaseUrl(); + + var content = GetContentUrl(assetLocation); + + sb.AppendLine($""); + return helper.Raw(sb.ToString()); } diff --git a/PlexRequests.UI/Modules/IssuesModule.cs b/PlexRequests.UI/Modules/IssuesModule.cs index c872b2608..ee835bbd4 100644 --- a/PlexRequests.UI/Modules/IssuesModule.cs +++ b/PlexRequests.UI/Modules/IssuesModule.cs @@ -38,10 +38,18 @@ namespace PlexRequests.UI.Modules 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); 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["/addnote", true] = async (x, ct) => await AddNote((int)Request.Form.requestId, (string)Request.Form.noteArea, (IssueState)(int)Request.Form.issue); } private IIssueService IssuesService { get; } @@ -56,6 +64,7 @@ namespace PlexRequests.UI.Modules private async Task GetIssues(IssueStatus status) { var issues = await IssuesService.GetAllAsync(); + issues = await FilterIssues(issues); var issuesModels = issues as IssuesModel[] ?? issues.Where(x => x.IssueStatus == status).ToArray(); var model = issuesModels.Select(i => new IssuesViewModel @@ -77,10 +86,30 @@ namespace PlexRequests.UI.Modules return Response.AsJson(count); } + public async Task TabCount() + { + var issues = await IssuesService.GetAllAsync(); + + var myIssues = await FilterIssues(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()}); + + return Response.AsJson(count); + } + public async Task Details(int id) { var issue = await IssuesService.GetAsync(id); - + issue = Order(issue); return issue == null ? Index() : View["Details", issue]; @@ -106,6 +135,16 @@ namespace PlexRequests.UI.Modules // An issue already exists if (existingIssue != null) { + if (existingIssue.Issues.Any(x => x.Issue == issue)) + { + return + Response.AsJson(new JsonResponseModel() + { + Result = false, + Message = "This issue has already been reported!" + }); + + } existingIssue.Issues.Add(model); var result = await IssuesService.UpdateIssueAsync(existingIssue); @@ -134,46 +173,104 @@ namespace PlexRequests.UI.Modules return Response.AsJson(new JsonResponseModel { Result = true }); } - private async Task> FilterIssues(IEnumerable issues) + private async Task> FilterIssues(IEnumerable issues) { var settings = await PlexRequestSettings.GetSettingsAsync(); - IEnumerable myIssues; + IEnumerable myIssues; if (IsAdmin) { - myIssues = issues.Where(x => x.Deleted == false).SelectMany(i => i.Issues); + myIssues = issues.Where(x => x.Deleted == false); } - else if (settings.UsersCanViewOnlyOwnRequests) + else if (settings.UsersCanViewOnlyOwnIssues) { - myIssues = (from issuesModel in issues - from i in issuesModel.Issues - where i.UserReported.Equals(Username, StringComparison.CurrentCultureIgnoreCase) - select i).ToList(); + myIssues = + issues.Where( + x => + x.Issues.Any(i => i.UserReported.Equals(Username, StringComparison.CurrentCultureIgnoreCase)) && x.Deleted == false); } else { - myIssues = issues.Where(x => x.Deleted == false).SelectMany(i => i.Issues); + myIssues = issues.Where(x => x.Deleted == false); } return myIssues; } - private async Task RemoveIssue(int issueId) + private async Task RemoveIssue(int issueId) { try { - this.RequiresClaims(UserClaims.PowerUser); + this.RequiresClaims(UserClaims.Admin); await IssuesService.DeleteIssueAsync(issueId); - return Response.AsJson(new JsonResponseModel {Result = true, Message = "Issue Removed"}); + return View["Index"]; } catch (Exception e) { Log.Error(e); - return Response.AsJson(new JsonResponseModel { Result = false, Message = "Looks like we couldn't remove the issue. Check the logs!" }); + return View["Index"]; } } + private async Task ChangeStatus(int issueId, IssueStatus status) + { + try + { + this.RequiresClaims(UserClaims.Admin); + var issue = await IssuesService.GetAsync(issueId); + issue.IssueStatus = status; + var result = await IssuesService.UpdateIssueAsync(issue); + return result ? await Details(issueId) : View["Index"]; + } + catch (Exception e) + { + Log.Error(e); + return View["Index"]; + } + + } + + + private async Task ClearIssue(int issueId, IssueState state) + { + this.RequiresClaims(UserClaims.Admin); + var issue = await IssuesService.GetAsync(issueId); + + var toRemove = issue.Issues.FirstOrDefault(x => x.Issue == state); + issue.Issues.Remove(toRemove); + + var result = await IssuesService.UpdateIssueAsync(issue); + + return result ? await Details(issueId) : View["Index"]; + } + + private async Task AddNote(int requestId, string noteArea, IssueState state) + { + this.RequiresClaims(UserClaims.Admin); + var issue = await IssuesService.GetAsync(requestId); + if (issue == null) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Issue does not exist to add a note!" }); + } + var toAddNote = issue.Issues.FirstOrDefault(x => x.Issue == state); + + issue.Issues.Remove(toAddNote); + toAddNote.AdminNote = noteArea; + issue.Issues.Add(toAddNote); + + + var result = await IssuesService.UpdateIssueAsync(issue); + return Response.AsJson(result + ? new JsonResponseModel { Result = true } + : new JsonResponseModel { Result = false, Message = "Could not update the notes, please try again or check the logs" }); + } + + private IssuesModel Order(IssuesModel issues) + { + issues.Issues = issues.Issues.OrderByDescending(x => x.Issue).ToList(); + return issues; + } } } diff --git a/PlexRequests.UI/Modules/RequestsModule.cs b/PlexRequests.UI/Modules/RequestsModule.cs index 54d28d708..2f2ff60e5 100644 --- a/PlexRequests.UI/Modules/RequestsModule.cs +++ b/PlexRequests.UI/Modules/RequestsModule.cs @@ -86,7 +86,6 @@ namespace PlexRequests.UI.Modules Post["/clearissues", true] = async (x, ct) => await ClearIssue((int)Request.Form.Id); Post["/changeavailability", true] = async (x, ct) => await ChangeRequestAvailability((int)Request.Form.Id, (bool)Request.Form.Available); - Post["/addnote", true] = async (x, ct) => await AddNote((int)Request.Form.requestId, (string)Request.Form.noteArea); } private static Logger Log = LogManager.GetCurrentClassLogger(); @@ -373,21 +372,6 @@ namespace PlexRequests.UI.Modules : new { Result = false, Available = false, Message = "Could not update the availability, please try again or check the logs" }); } - private async Task AddNote(int requestId, string noteArea) - { - this.RequiresClaims(UserClaims.Admin); - var originalRequest = await Service.GetAsync(requestId); - if (originalRequest == null) - { - return Response.AsJson(new JsonResponseModel { Result = false, Message = "Request does not exist to add a note!" }); - } - - originalRequest.AdminNote = noteArea; - - var result = await Service.UpdateRequestAsync(originalRequest); - return Response.AsJson(result - ? new JsonResponseModel { Result = true } - : new JsonResponseModel { Result = false, Message = "Could not update the notes, please try again or check the logs" }); - } + } } diff --git a/PlexRequests.UI/PlexRequests.UI.csproj b/PlexRequests.UI/PlexRequests.UI.csproj index a71061777..03595ad45 100644 --- a/PlexRequests.UI/PlexRequests.UI.csproj +++ b/PlexRequests.UI/PlexRequests.UI.csproj @@ -243,6 +243,9 @@ + + PreserveNewest + PreserveNewest diff --git a/PlexRequests.UI/Views/Admin/Settings.cshtml b/PlexRequests.UI/Views/Admin/Settings.cshtml index 84f7233e1..be5a6576d 100644 --- a/PlexRequests.UI/Views/Admin/Settings.cshtml +++ b/PlexRequests.UI/Views/Admin/Settings.cshtml @@ -164,20 +164,39 @@
- @if (Model.UsersCanViewOnlyOwnRequests) - { - - - } - else - { - - } - + @if (Model.UsersCanViewOnlyOwnRequests) + { + + + } + else + { + + } + + +
+
+ +
+
+ + @if (Model.UsersCanViewOnlyOwnIssues) + { + + + } + else + { + + } +
+ +

A comma separated list of users whose requests do not require approval.

diff --git a/PlexRequests.UI/Views/Issues/Details.cshtml b/PlexRequests.UI/Views/Issues/Details.cshtml index f451f1ac2..eb69a04d0 100644 --- a/PlexRequests.UI/Views/Issues/Details.cshtml +++ b/PlexRequests.UI/Views/Issues/Details.cshtml @@ -1,14 +1,116 @@ - +@using System.Linq +@using PlexRequests.Core.Models +@using PlexRequests.UI.Helpers +@{ + var baseUrl = Html.GetBaseUrl(); + var formAction = string.Empty; + if (!string.IsNullOrEmpty(baseUrl.ToHtmlString())) + { + formAction = "/" + baseUrl.ToHtmlString(); + } + + var isAdmin = false; + + if (Context.CurrentUser != null) + { + var claims = Context.CurrentUser.Claims.ToList(); + if (claims.Contains("Admin") || claims.Contains("PowerUser")) + { + isAdmin = true; + } + } +}

Details

-

Issues For @Model.Title

-
- +
+
+ +
+
+

Issues For "@Model.Title"

+
+ @if (isAdmin) + { +
+ + @if (Model.IssueStatus == IssueStatus.PendingIssue) + { +
+ + +
+ } + @if (Model.IssueStatus == IssueStatus.InProgressIssue) + { +
+ + +
+ } + @if (Model.IssueStatus == IssueStatus.ResolvedIssue) + { +
+ + +
+ } +
+ } +
+ + +
+ +
@foreach (var issue in Model.Issues) { -
Type: @issue.Issue
-
User Reported: @issue.UserReported
-
User Note: @issue.UserNote
-
Admin Note: @issue.AdminNote
-} \ No newline at end of file +
+
+
Type: @StringHelper.CamelCaseToWords(issue.Issue.ToString())
+
User Reported: @issue.UserReported
+
User Note: @issue.UserNote
+
Admin Note:@issue.AdminNote
+
+ @if (isAdmin) + { +
+
+ + + + +
+
+
+ +
+ } +
+
+
+} + + + +@Html.LoadIssueDetailsAssets() \ No newline at end of file diff --git a/PlexRequests.UI/Views/Issues/Index.cshtml b/PlexRequests.UI/Views/Issues/Index.cshtml index 7621843c5..38a7fe5b7 100644 --- a/PlexRequests.UI/Views/Issues/Index.cshtml +++ b/PlexRequests.UI/Views/Issues/Index.cshtml @@ -3,8 +3,66 @@

Below you can see yours and all your current issues and their state.



-

Pending Issues


-
+ + +
+
+
+
+

Title

+
+
+

Type

+
+
+

Issue's

+
+ +
+

Requested

+
+
+ +
+
+ +
+ +
+
+
+ +
+ +
+
+ + +
+ +
+
+ +
+ +
+
+ + +
+ +
+
+ +
+ +
+
+
-@Html.LoadIssueAssets() \ No newline at end of file +@Html.LoadIssueAssets() diff --git a/PlexRequests.UI/Views/Requests/Index.cshtml b/PlexRequests.UI/Views/Requests/Index.cshtml index 5ca96c171..66073161b 100644 --- a/PlexRequests.UI/Views/Requests/Index.cshtml +++ b/PlexRequests.UI/Views/Requests/Index.cshtml @@ -183,7 +183,7 @@ {{#if_eq issueId 0}} {{else}} - + {{/if_eq}}
@@ -328,11 +328,6 @@ -
- - -
-
{{#if_eq available true}}