mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-10 15:32:37 -07:00
a crap tonne of work on #273
This commit is contained in:
parent
d6c2997570
commit
071daf4ab4
16 changed files with 472 additions and 103 deletions
|
@ -41,6 +41,7 @@ namespace PlexRequests.Core.SettingModels
|
||||||
public bool RequireTvShowApproval { get; set; }
|
public bool RequireTvShowApproval { get; set; }
|
||||||
public bool RequireMusicApproval { get; set; }
|
public bool RequireMusicApproval { get; set; }
|
||||||
public bool UsersCanViewOnlyOwnRequests { get; set; }
|
public bool UsersCanViewOnlyOwnRequests { get; set; }
|
||||||
|
public bool UsersCanViewOnlyOwnIssues { get; set; }
|
||||||
public int WeeklyRequestLimit { get; set; }
|
public int WeeklyRequestLimit { get; set; }
|
||||||
public string NoApprovalUsers { get; set; }
|
public string NoApprovalUsers { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -156,3 +156,17 @@ button.list-group-item:focus {
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
outline: 0; }
|
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; }
|
||||||
|
|
||||||
|
|
2
PlexRequests.UI/Content/Themes/plex.min.css
vendored
2
PlexRequests.UI/Content/Themes/plex.min.css
vendored
|
@ -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;}
|
.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;}
|
|
@ -194,3 +194,18 @@ button.list-group-item:focus {
|
||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
outline: 0;
|
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;
|
||||||
|
}
|
46
PlexRequests.UI/Content/issue-details.js
Normal file
46
PlexRequests.UI/Content/issue-details.js
Normal file
|
@ -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);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,16 @@ var base = $('#baseUrl').text();
|
||||||
|
|
||||||
initLoad();
|
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
|
// Report Issue
|
||||||
|
@ -179,14 +189,58 @@ $(document).on("click", ".clear", function (e) {
|
||||||
|
|
||||||
|
|
||||||
function initLoad() {
|
function initLoad() {
|
||||||
|
loadCounts();
|
||||||
loadPendingIssues();
|
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() {
|
||||||
|
loadIssues("pending", $('#pendingIssues'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function loadPendingIssues() {
|
function loadInProgressIssues() {
|
||||||
$issues = $('#pendingIssues');
|
var $element = $('#inprogressIssues');
|
||||||
var url = createBaseUrl(base, "issues/pending");
|
$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/");
|
var linkUrl = createBaseUrl(base, "issues/");
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "get",
|
type: "get",
|
||||||
|
@ -194,12 +248,12 @@ function loadPendingIssues() {
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
if (response.length > 0) {
|
if (response.length > 0) {
|
||||||
response.forEach(function(result) {
|
response.forEach(function (result) {
|
||||||
var context = buildIssueContext(result);
|
var context = buildIssueContext(result);
|
||||||
var html = issueTemplate(context);
|
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");
|
generateNotify("Could not load Pending issues", "danger");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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("<div>Issue: None</div>");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function (e) {
|
|
||||||
console.log(e);
|
|
||||||
generateNotify("Something went wrong!", "danger");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
// Change Availability
|
// Change Availability
|
||||||
$(document).on("click", ".change", function (e) {
|
$(document).on("click", ".change", function (e) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ function loadingButton(elementId, originalCss) {
|
||||||
$element.removeClass("btn-" + originalCss + "-outline").addClass("btn-primary-outline").addClass('disabled').html("<i class='fa fa-spinner fa-spin'></i> Loading...");
|
$element.removeClass("btn-" + originalCss + "-outline").addClass("btn-primary-outline").addClass('disabled').html("<i class='fa fa-spinner fa-spin'></i> Loading...");
|
||||||
|
|
||||||
// handle split-buttons
|
// handle split-buttons
|
||||||
var $dropdown = $element.next('.dropdown-toggle')
|
var $dropdown = $element.next('.dropdown-toggle');
|
||||||
if ($dropdown.length > 0) {
|
if ($dropdown.length > 0) {
|
||||||
$dropdown.removeClass("btn-" + originalCss + "-outline").addClass("btn-primary-outline").addClass('disabled');
|
$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);
|
$element.removeClass("btn-primary-outline").removeClass('disabled').addClass("btn-" + originalCss + "-outline").html(html);
|
||||||
|
|
||||||
// handle split-buttons
|
// handle split-buttons
|
||||||
var $dropdown = $element.next('.dropdown-toggle')
|
var $dropdown = $element.next('.dropdown-toggle');
|
||||||
if ($dropdown.length > 0) {
|
if ($dropdown.length > 0) {
|
||||||
$dropdown.removeClass("btn-primary-outline").removeClass('disabled').addClass("btn-" + originalCss + "-outline");
|
$dropdown.removeClass("btn-primary-outline").removeClass('disabled').addClass("btn-" + originalCss + "-outline");
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,18 @@ namespace PlexRequests.UI.Helpers
|
||||||
|
|
||||||
sb.AppendLine($"<script src=\"{content}/Content/issues.js\" type=\"text/javascript\"></script>");
|
sb.AppendLine($"<script src=\"{content}/Content/issues.js\" type=\"text/javascript\"></script>");
|
||||||
|
|
||||||
|
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($"<script src=\"{content}/Content/issue-details.js\" type=\"text/javascript\"></script>");
|
||||||
|
|
||||||
return helper.Raw(sb.ToString());
|
return helper.Raw(sb.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,10 +38,18 @@ namespace PlexRequests.UI.Modules
|
||||||
Get["/resolved", true] = async (x, ct) => await GetIssues(IssueStatus.ResolvedIssue);
|
Get["/resolved", true] = async (x, ct) => await GetIssues(IssueStatus.ResolvedIssue);
|
||||||
|
|
||||||
Post["/remove", true] = async (x, ct) => await RemoveIssue((int)Request.Form.issueId);
|
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["/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 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; }
|
private IIssueService IssuesService { get; }
|
||||||
|
@ -56,6 +64,7 @@ namespace PlexRequests.UI.Modules
|
||||||
private async Task<Response> GetIssues(IssueStatus status)
|
private async Task<Response> GetIssues(IssueStatus status)
|
||||||
{
|
{
|
||||||
var issues = await IssuesService.GetAllAsync();
|
var issues = await IssuesService.GetAllAsync();
|
||||||
|
issues = await FilterIssues(issues);
|
||||||
|
|
||||||
var issuesModels = issues as IssuesModel[] ?? issues.Where(x => x.IssueStatus == status).ToArray();
|
var issuesModels = issues as IssuesModel[] ?? issues.Where(x => x.IssueStatus == status).ToArray();
|
||||||
var model = issuesModels.Select(i => new IssuesViewModel
|
var model = issuesModels.Select(i => new IssuesViewModel
|
||||||
|
@ -77,10 +86,30 @@ namespace PlexRequests.UI.Modules
|
||||||
return Response.AsJson(count);
|
return Response.AsJson(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Response> TabCount()
|
||||||
|
{
|
||||||
|
var issues = await IssuesService.GetAllAsync();
|
||||||
|
|
||||||
|
var myIssues = await FilterIssues(issues);
|
||||||
|
|
||||||
|
var count = new List<object>();
|
||||||
|
|
||||||
|
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<Negotiator> Details(int id)
|
public async Task<Negotiator> Details(int id)
|
||||||
{
|
{
|
||||||
var issue = await IssuesService.GetAsync(id);
|
var issue = await IssuesService.GetAsync(id);
|
||||||
|
issue = Order(issue);
|
||||||
return issue == null
|
return issue == null
|
||||||
? Index()
|
? Index()
|
||||||
: View["Details", issue];
|
: View["Details", issue];
|
||||||
|
@ -106,6 +135,16 @@ namespace PlexRequests.UI.Modules
|
||||||
// An issue already exists
|
// An issue already exists
|
||||||
if (existingIssue != null)
|
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);
|
existingIssue.Issues.Add(model);
|
||||||
var result = await IssuesService.UpdateIssueAsync(existingIssue);
|
var result = await IssuesService.UpdateIssueAsync(existingIssue);
|
||||||
|
|
||||||
|
@ -134,46 +173,104 @@ namespace PlexRequests.UI.Modules
|
||||||
return Response.AsJson(new JsonResponseModel { Result = true });
|
return Response.AsJson(new JsonResponseModel { Result = true });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IEnumerable<IssueModel>> FilterIssues(IEnumerable<IssuesModel> issues)
|
private async Task<IEnumerable<IssuesModel>> FilterIssues(IEnumerable<IssuesModel> issues)
|
||||||
{
|
{
|
||||||
var settings = await PlexRequestSettings.GetSettingsAsync();
|
var settings = await PlexRequestSettings.GetSettingsAsync();
|
||||||
IEnumerable<IssueModel> myIssues;
|
IEnumerable<IssuesModel> myIssues;
|
||||||
if (IsAdmin)
|
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
|
myIssues =
|
||||||
from i in issuesModel.Issues
|
issues.Where(
|
||||||
where i.UserReported.Equals(Username, StringComparison.CurrentCultureIgnoreCase)
|
x =>
|
||||||
select i).ToList();
|
x.Issues.Any(i => i.UserReported.Equals(Username, StringComparison.CurrentCultureIgnoreCase)) && x.Deleted == false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
myIssues = issues.Where(x => x.Deleted == false).SelectMany(i => i.Issues);
|
myIssues = issues.Where(x => x.Deleted == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return myIssues;
|
return myIssues;
|
||||||
}
|
}
|
||||||
private async Task<Response> RemoveIssue(int issueId)
|
private async Task<Negotiator> RemoveIssue(int issueId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.RequiresClaims(UserClaims.PowerUser);
|
this.RequiresClaims(UserClaims.Admin);
|
||||||
|
|
||||||
await IssuesService.DeleteIssueAsync(issueId);
|
await IssuesService.DeleteIssueAsync(issueId);
|
||||||
|
|
||||||
return Response.AsJson(new JsonResponseModel {Result = true, Message = "Issue Removed"});
|
return View["Index"];
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Error(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<Negotiator> 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<Negotiator> 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<Response> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,6 @@ namespace PlexRequests.UI.Modules
|
||||||
Post["/clearissues", true] = async (x, ct) => await ClearIssue((int)Request.Form.Id);
|
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["/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();
|
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" });
|
: new { Result = false, Available = false, Message = "Could not update the availability, please try again or check the logs" });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Response> 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" });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,6 +243,9 @@
|
||||||
<Compile Include="Startup.cs" />
|
<Compile Include="Startup.cs" />
|
||||||
<Compile Include="Validators\PlexRequestsValidator.cs" />
|
<Compile Include="Validators\PlexRequestsValidator.cs" />
|
||||||
<Compile Include="Modules\UserManagementModule.cs" />
|
<Compile Include="Modules\UserManagementModule.cs" />
|
||||||
|
<Content Include="Content\issue-details.js">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="Content\issues.js">
|
<Content Include="Content\issues.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
|
@ -164,20 +164,39 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
|
|
||||||
@if (Model.UsersCanViewOnlyOwnRequests)
|
@if (Model.UsersCanViewOnlyOwnRequests)
|
||||||
{
|
{
|
||||||
<input type="checkbox" id="UsersCanViewOnlyOwnRequests" name="UsersCanViewOnlyOwnRequests" checked="checked">
|
<input type="checkbox" id="UsersCanViewOnlyOwnRequests" name="UsersCanViewOnlyOwnRequests" checked="checked">
|
||||||
<label for="UsersCanViewOnlyOwnRequests">Users can view their own requests only</label>
|
<label for="UsersCanViewOnlyOwnRequests">Users can view their own requests only</label>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<input type="checkbox" id="UsersCanViewOnlyOwnRequests" name="UsersCanViewOnlyOwnRequests"><label for="UsersCanViewOnlyOwnRequests">Users can view their own requests only</label>
|
<input type="checkbox" id="UsersCanViewOnlyOwnRequests" name="UsersCanViewOnlyOwnRequests"><label for="UsersCanViewOnlyOwnRequests">Users can view their own requests only</label>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
|
||||||
|
@if (Model.UsersCanViewOnlyOwnIssues)
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="UsersCanViewOnlyOwnIssues" name="UsersCanViewOnlyOwnIssues" checked="checked">
|
||||||
|
<label for="UsersCanViewOnlyOwnIssues">Users can view their own issues only</label>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="UsersCanViewOnlyOwnIssues" name="UsersCanViewOnlyOwnIssues"><label for="UsersCanViewOnlyOwnIssues">Users can view their own issues only</label>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p class="form-group">A comma separated list of users whose requests do not require approval.</p>
|
<p class="form-group">A comma separated list of users whose requests do not require approval.</p>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="noApprovalUsers" class="control-label">Approval White listed Users</label>
|
<label for="noApprovalUsers" class="control-label">Approval White listed Users</label>
|
||||||
|
|
|
@ -1,14 +1,116 @@
|
||||||
|
@using System.Linq
|
||||||
<h1>Details</h1>
|
@using PlexRequests.Core.Models
|
||||||
<h4>Issues For @Model.Title</h4>
|
@using PlexRequests.UI.Helpers
|
||||||
<br />
|
@{
|
||||||
|
var baseUrl = Html.GetBaseUrl();
|
||||||
|
var formAction = string.Empty;
|
||||||
|
if (!string.IsNullOrEmpty(baseUrl.ToHtmlString()))
|
||||||
|
{
|
||||||
|
formAction = "/" + baseUrl.ToHtmlString();
|
||||||
|
}
|
||||||
|
|
||||||
<img src="@Model.PosterUrl" />
|
var isAdmin = false;
|
||||||
|
|
||||||
|
if (Context.CurrentUser != null)
|
||||||
|
{
|
||||||
|
var claims = Context.CurrentUser.Claims.ToList();
|
||||||
|
if (claims.Contains("Admin") || claims.Contains("PowerUser"))
|
||||||
|
{
|
||||||
|
isAdmin = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<h1>Details</h1>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<img src="@Model.PosterUrl" />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<h4>Issues For "@Model.Title"</h4>
|
||||||
|
</div>
|
||||||
|
@if (isAdmin)
|
||||||
|
{
|
||||||
|
<div class="col-md-2">
|
||||||
|
|
||||||
|
@if (Model.IssueStatus == IssueStatus.PendingIssue)
|
||||||
|
{
|
||||||
|
<form action="@formAction/issues/inprogressUpdate" method="post">
|
||||||
|
<input id="issueId" name="issueId" value="@Model.Id" hidden="hidden" />
|
||||||
|
<button id="@Model.Id" class="btn btn-sm btn-primary-outline dropdown-toggle inProgress">In-Progress</button>
|
||||||
|
</form>
|
||||||
|
}
|
||||||
|
@if (Model.IssueStatus == IssueStatus.InProgressIssue)
|
||||||
|
{
|
||||||
|
<form action="@formAction/issues/resolvedUpdate" method="post">
|
||||||
|
<input id="issueId" name="issueId" value="@Model.Id" hidden="hidden" />
|
||||||
|
<button type="submit" id="@Model.Id" class="btn btn-sm btn-success-outline dropdown-toggle resolve">Resolve</button>
|
||||||
|
</form>
|
||||||
|
}
|
||||||
|
@if (Model.IssueStatus == IssueStatus.ResolvedIssue)
|
||||||
|
{
|
||||||
|
<form action="@formAction/issues/remove" method="post">
|
||||||
|
<input id="issueId" name="issueId" value="@Model.Id" hidden="hidden" />
|
||||||
|
<button type="submit" id="@Model.Id" class="btn btn-sm btn-danger-outline dropdown-toggle delete">Remove</button>
|
||||||
|
</form>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<br />
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
@foreach (var issue in Model.Issues)
|
@foreach (var issue in Model.Issues)
|
||||||
{
|
{
|
||||||
<div>Type: @issue.Issue</div>
|
<div class="row">
|
||||||
<div>User Reported: @issue.UserReported</div>
|
<div class="col-sm-11">
|
||||||
<div>User Note: @issue.UserNote</div>
|
<div><strong>Type:</strong> @StringHelper.CamelCaseToWords(issue.Issue.ToString())</div>
|
||||||
<div>Admin Note: @issue.AdminNote</div>
|
<div><strong>User Reported:</strong> @issue.UserReported</div>
|
||||||
}
|
<div><strong>User Note:</strong> @issue.UserNote</div>
|
||||||
|
<div><strong>Admin Note:</strong>@issue.AdminNote</div>
|
||||||
|
</div>
|
||||||
|
@if (isAdmin)
|
||||||
|
{
|
||||||
|
<div class="col-sm-1">
|
||||||
|
<form action="@formAction/issues/clear" method="post">
|
||||||
|
<input name="issueId" value="@Model.Id" hidden="hidden" />
|
||||||
|
<input name="issue" value="@((int) issue.Issue)" hidden="hidden" />
|
||||||
|
|
||||||
|
<button type="submit" id="@Model.Id" class="btn btn-sm btn-info-outline dropdown-toggle">Clear</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-1">
|
||||||
|
<button id="@Model.Id" issue-select="4" class="note btn btn-sm btn-primary-outline dropdown-toggle" data-identifier="@Model.Id" data-issue="@((int) issue.Issue)" href="#" data-toggle="modal" data-target="#noteModal">Add Note</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<hr />
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="modal fade" id="noteModal">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-times"></i></button>
|
||||||
|
<h4 class="modal-title">Add a note</h4>
|
||||||
|
</div>
|
||||||
|
<form method="POST" action="@formAction/issues/addnote" id="noteForm">
|
||||||
|
<div class="modal-body">
|
||||||
|
<input name="requestId" class="noteId" type="text" hidden="hidden" value="" />
|
||||||
|
<input name="issue" class="issue" type="text" hidden="hidden" value="" />
|
||||||
|
<textarea class="form-control form-control-custom" rows="3" id="noteArea" name="noteArea"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-danger-outline" data-dismiss="modal">Close</button>
|
||||||
|
<button type="button" class="btn btn-primary-outline theNoteSaveButton" data-dismiss="modal">Save changes</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@Html.LoadIssueDetailsAssets()
|
|
@ -3,8 +3,66 @@
|
||||||
<h4>Below you can see yours and all your current issues and their state.</h4>
|
<h4>Below you can see yours and all your current issues and their state.</h4>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<h3>Pending Issues</h3><hr />
|
|
||||||
<div id="pendingIssues"></div>
|
<ul id="nav-tabs" class="nav nav-tabs" role="tablist">
|
||||||
|
<li role="presentation" class="active"><a href="#pendingTab" aria-controls="home" role="tab" data-toggle="tab">Pending <span id="pendingCount"></span></a></li>
|
||||||
|
<li role="presentation"><a href="#inProgressTab" aria-controls="profile" role="tab" data-toggle="tab">In-Progress <span id="inProgressCount"></span></a></li>
|
||||||
|
<li role="presentation"><a href="#resolvedTab" aria-controls="profile" role="tab" data-toggle="tab">Resolved <span id="resolvedCount"></span></a></li>
|
||||||
|
</ul>
|
||||||
|
<br/>
|
||||||
|
<hr/>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<h4>Title</h4>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2">
|
||||||
|
<h4>Type</h4>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-1">
|
||||||
|
<h4>Issue's</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-2">
|
||||||
|
<h4>Requested</h4>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3 col-sm-push-3">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="myTabContent" class="tab-content">
|
||||||
|
<!-- Pending tab -->
|
||||||
|
<div role="tabpanel" class="tab-pane active" id="pendingTab">
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<!-- Movie content -->
|
||||||
|
<div id="pendingIssues">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--In Progress-->
|
||||||
|
<div role="tabpanel" class="tab-pane" id="inProgressTab">
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<!-- In progress content -->
|
||||||
|
<div id="inprogressIssues">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Resolved -->
|
||||||
|
<div role="tabpanel" class="tab-pane" id="resolvedTab">
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<!-- resolved content -->
|
||||||
|
<div id="resolvedIssues">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script id="issue-template" type="text/x-handlebars-template">
|
<script id="issue-template" type="text/x-handlebars-template">
|
||||||
<div>
|
<div>
|
||||||
|
@ -21,22 +79,17 @@
|
||||||
|
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
{{#if requestId}}
|
{{#if requestId}}
|
||||||
<div>Request {{requestId}}</div>
|
<div><i class="fa fa-check"></i></div>
|
||||||
|
{{else}}
|
||||||
|
<div><i class="fa fa-times"></i></div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3 col-sm-push-3">
|
<div class="col-sm-3 col-sm-push-3">
|
||||||
<a href="" id="{{id}}link" class="btn btn-sm btn-info-outline approve"><i class="fa fa-info"></i> Details</a>
|
<a href="" id="{{id}}link" class="btn btn-sm btn-info-outline approve"><i class="fa fa-info"></i> Details</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@Html.LoadIssueAssets()
|
@Html.LoadIssueAssets()
|
||||||
|
|
|
@ -183,7 +183,7 @@
|
||||||
{{#if_eq issueId 0}}
|
{{#if_eq issueId 0}}
|
||||||
<i class="fa fa-times"></i>
|
<i class="fa fa-times"></i>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a href="/issues/{{issueId}}"><i class="fa fa-check"></i></a>
|
<a href="@formAction/issues/{{issueId}}"><i class="fa fa-check"></i></a>
|
||||||
{{/if_eq}}
|
{{/if_eq}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -328,11 +328,6 @@
|
||||||
<button id="{{requestId}}" style="text-align: right" class="btn btn-sm btn-danger-outline delete" type="submit"><i class="fa fa-minus"></i> Remove</button>
|
<button id="{{requestId}}" style="text-align: right" class="btn btn-sm btn-danger-outline delete" type="submit"><i class="fa fa-minus"></i> Remove</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form method="POST" action="@formAction/requests/clearissues" id="clear{{requestId}}">
|
|
||||||
<input name="Id" type="text" value="{{requestId}}" hidden="hidden" />
|
|
||||||
<button id="{{requestId}}" style="text-align: right" class="btn btn-sm btn-info-outline clear" type="submit"><i class="fa fa-check"></i> Clear Issues</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form method="POST" action="@formAction/requests/changeavailability" id="change{{requestId}}">
|
<form method="POST" action="@formAction/requests/changeavailability" id="change{{requestId}}">
|
||||||
<input name="Id" type="text" value="{{requestId}}" hidden="hidden" />
|
<input name="Id" type="text" value="{{requestId}}" hidden="hidden" />
|
||||||
{{#if_eq available true}}
|
{{#if_eq available true}}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue