Some error handling and ensure we are an admin to delete requests.

Also started on the approval of everything
This commit is contained in:
tidusjar 2016-03-08 14:26:26 +00:00
parent 2935bee30d
commit 0942bfcbcc
18 changed files with 436 additions and 58 deletions

View file

@ -0,0 +1,48 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: ApplicationSettingsException.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;
namespace PlexRequests.Helpers.Exceptions
{
public class ApplicationSettingsException : Exception
{
public ApplicationSettingsException(string message) : base(message)
{
}
public ApplicationSettingsException(string message, Exception innerException) : base(message, innerException)
{
}
public ApplicationSettingsException()
{
}
}
}

View file

@ -47,6 +47,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="AssemblyHelper.cs" /> <Compile Include="AssemblyHelper.cs" />
<Compile Include="Exceptions\ApplicationSettingsException.cs" />
<Compile Include="ICacheProvider.cs" /> <Compile Include="ICacheProvider.cs" />
<Compile Include="LoggingHelper.cs" /> <Compile Include="LoggingHelper.cs" />
<Compile Include="MemoryCacheProvider.cs" /> <Compile Include="MemoryCacheProvider.cs" />
@ -59,6 +60,7 @@
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View file

@ -1,5 +1,7 @@
using System; using System;
using PlexRequests.Helpers.Exceptions;
namespace PlexRequests.Helpers namespace PlexRequests.Helpers
{ {
public static class UriHelper public static class UriHelper
@ -7,6 +9,10 @@ namespace PlexRequests.Helpers
public static Uri ReturnUri(this string val) public static Uri ReturnUri(this string val)
{ {
if (val == null)
{
throw new ApplicationSettingsException("The URI is null, please check your settings to make sure you have configured the applications correctly.");
}
try try
{ {
var uri = new UriBuilder(); var uri = new UriBuilder();
@ -53,6 +59,10 @@ namespace PlexRequests.Helpers
/// <exception cref="System.Exception"></exception> /// <exception cref="System.Exception"></exception>
public static Uri ReturnUri(this string val, int port) public static Uri ReturnUri(this string val, int port)
{ {
if (val == null)
{
throw new ApplicationSettingsException("The URI is null, please check your settings to make sure you have configured the applications correctly.");
}
try try
{ {
var uri = new UriBuilder(); var uri = new UriBuilder();
@ -65,7 +75,7 @@ namespace PlexRequests.Helpers
uri = new UriBuilder(Uri.UriSchemeHttp, split[2], port, "/" + split[3]); uri = new UriBuilder(Uri.UriSchemeHttp, split[2], port, "/" + split[3]);
} }
else else
uri = new UriBuilder(new Uri(string.Format("{0}:{1}", val, port))); uri = new UriBuilder(new Uri($"{val}:{port}"));
} }
else if (val.StartsWith("https://", StringComparison.Ordinal)) else if (val.StartsWith("https://", StringComparison.Ordinal))
{ {

View file

@ -27,6 +27,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NLog;
using PlexRequests.Api; using PlexRequests.Api;
using PlexRequests.Core; using PlexRequests.Core;
using PlexRequests.Core.SettingModels; using PlexRequests.Core.SettingModels;
@ -47,6 +49,7 @@ namespace PlexRequests.Services
private ISettingsService<PlexSettings> Plex { get; } private ISettingsService<PlexSettings> Plex { get; }
private ISettingsService<AuthenticationSettings> Auth { get; } private ISettingsService<AuthenticationSettings> Auth { get; }
private IRequestService RequestService { get; } private IRequestService RequestService { get; }
private static Logger Log = LogManager.GetCurrentClassLogger();
public void CheckAndUpdateAll(long check) public void CheckAndUpdateAll(long check)
@ -54,6 +57,18 @@ namespace PlexRequests.Services
var plexSettings = Plex.GetSettings(); var plexSettings = Plex.GetSettings();
var authSettings = Auth.GetSettings(); var authSettings = Auth.GetSettings();
var requests = RequestService.GetAll(); var requests = RequestService.GetAll();
if (plexSettings.Ip == null || authSettings.PlexAuthToken == null || requests == null)
{
Log.Warn("A setting is null, Ensure Plex is configured correctly, and we have a Plex Auth token.");
return;
}
if (!requests.Any())
{
Log.Info("We have no requests to check if they are available on Plex.");
return;
}
var api = new PlexApi(); var api = new PlexApi();
var modifiedModel = new List<RequestedModel>(); var modifiedModel = new List<RequestedModel>();

View file

@ -30,6 +30,10 @@ using System.Linq;
using Dapper.Contrib.Extensions; using Dapper.Contrib.Extensions;
using NLog;
using PlexRequests.Helpers;
namespace PlexRequests.Store namespace PlexRequests.Store
{ {
public class GenericRepository<T> : IRepository<T> where T : Entity public class GenericRepository<T> : IRepository<T> where T : Entity
@ -39,6 +43,8 @@ namespace PlexRequests.Store
Config = config; Config = config;
} }
private static Logger Log = LogManager.GetCurrentClassLogger();
private ISqliteConfiguration Config { get; set; } private ISqliteConfiguration Config { get; set; }
public long Insert(T entity) public long Insert(T entity)
{ {
@ -84,6 +90,8 @@ namespace PlexRequests.Store
public bool Update(T entity) public bool Update(T entity)
{ {
Log.Trace("Updating entity");
Log.Trace(entity.DumpJson());
using (var db = Config.DbConnection()) using (var db = Config.DbConnection())
{ {
db.Open(); db.Open();
@ -93,7 +101,9 @@ namespace PlexRequests.Store
public bool UpdateAll(IEnumerable<T> entity) public bool UpdateAll(IEnumerable<T> entity)
{ {
Log.Trace("Updating all entities");
var result = new HashSet<bool>(); var result = new HashSet<bool>();
using (var db = Config.DbConnection()) using (var db = Config.DbConnection())
{ {
db.Open(); db.Open();

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Security.Cryptography;
using Dapper.Contrib.Extensions; using Dapper.Contrib.Extensions;
@ -20,7 +21,8 @@ namespace PlexRequests.Store
public string RequestedBy { get; set; } public string RequestedBy { get; set; }
public DateTime RequestedDate { get; set; } public DateTime RequestedDate { get; set; }
public bool Available { get; set; } public bool Available { get; set; }
public IssueState Issues { get; set; }
public string OtherMessage { get; set; }
} }
public enum RequestType public enum RequestType
@ -28,4 +30,13 @@ namespace PlexRequests.Store
Movie, Movie,
TvShow TvShow
} }
public enum IssueState
{
WrongAudio,
NoSubtitles,
WrongContent,
PlaybackIssues,
Other
}
} }

View file

@ -22,7 +22,7 @@ CREATE TABLE IF NOT EXISTS Requested
Type INTEGER NOT NULL, Type INTEGER NOT NULL,
ProviderId INTEGER NOT NULL, ProviderId INTEGER NOT NULL,
ImdbId varchar(50), ImdbId varchar(50),
Overview varchar(50) NOT NULL, Overview varchar(50),
Title varchar(50) NOT NULL, Title varchar(50) NOT NULL,
PosterPath varchar(50) NOT NULL, PosterPath varchar(50) NOT NULL,
ReleaseDate varchar(50) NOT NULL, ReleaseDate varchar(50) NOT NULL,
@ -30,7 +30,9 @@ CREATE TABLE IF NOT EXISTS Requested
Approved INTEGER NOT NULL, Approved INTEGER NOT NULL,
RequestedBy varchar(50), RequestedBy varchar(50),
RequestedDate varchar(50) NOT NULL, RequestedDate varchar(50) NOT NULL,
Available INTEGER(50) Available INTEGER(50),
Issues INTEGER,
OtherMessage varchar(50)
); );

View file

@ -18,3 +18,4 @@
background-color: #4e5d6c !important; background-color: #4e5d6c !important;
color: white !important; color: white !important;
} }

View file

@ -13,6 +13,67 @@ var tvimer = 0;
movieLoad(); movieLoad();
tvLoad(); tvLoad();
$('#approveAll').click(function() {
$.ajax({
type: 'post',
url: '/approval/approveall',
dataType: "json",
success: function (response) {
if (checkJsonResponse(response)) {
generateNotify("Success!", "success");
}
},
error: function (e) {
console.log(e);
generateNotify("Something went wrong!", "danger");
}
});
});
// 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;
}
$.ajax({
type: "post",
url: "/requests/reportissue",
data: $form.serialize(), // TODO pass in issue enum and Id
dataType: "json",
success: function (response) {
if (checkJsonResponse(response)) {
generateNotify("Success!", "success");
$("#" + buttonId + "Template").slideUp();
}
},
error: function (e) {
console.log(e);
generateNotify("Something went wrong!", "danger");
}
});
});
// Modal click
$('.theSaveButton').click(function() {
});
// Update the modal
$('#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);
});
$(document).on("click", ".delete", function (e) { $(document).on("click", ".delete", function (e) {
e.preventDefault(); e.preventDefault();
var buttonId = e.target.id; var buttonId = e.target.id;
@ -24,13 +85,11 @@ $(document).on("click", ".delete", function (e) {
data: $form.serialize(), data: $form.serialize(),
dataType: "json", dataType: "json",
success: function (response) { success: function (response) {
console.log(response);
if (response.result === true) { if (checkJsonResponse(response)) {
generateNotify("Success!", "success"); generateNotify("Success!", "success");
$("#" + buttonId + "Template").slideUp(); $("#" + buttonId + "Template").slideUp();
} else {
generateNotify(response.message, "warning");
} }
}, },
error: function (e) { error: function (e) {
@ -81,7 +140,8 @@ function buildRequestContext(result, type) {
approved: result.approved, approved: result.approved,
requestedBy: result.requestedBy, requestedBy: result.requestedBy,
requestedDate: result.requestedDate, requestedDate: result.requestedDate,
available: result.available available: result.available,
admin: result.admin
}; };
return context; return context;

View file

@ -10,14 +10,14 @@ var searchTemplate = Handlebars.compile(searchSource);
var movieTimer = 0; var movieTimer = 0;
var tvimer = 0; var tvimer = 0;
$("#movieSearchContent").keypress(function (e) { $("#movieSearchContent").keypress(function () {
if (movieTimer) { if (movieTimer) {
clearTimeout(movieTimer); clearTimeout(movieTimer);
} }
movieTimer = setTimeout(movieSearch, 400); movieTimer = setTimeout(movieSearch, 400);
}); });
$("#tvSearchContent").keypress(function (e) { $("#tvSearchContent").keypress(function () {
if (tvimer) { if (tvimer) {
clearTimeout(tvimer); clearTimeout(tvimer);
} }
@ -26,12 +26,17 @@ $("#tvSearchContent").keypress(function (e) {
// Click TV dropdown option // Click TV dropdown option
$(document).on("click", ".dropdownTv", function (e) { $(document).on("click", ".dropdownTv", function (e) {
e.preventDefault();
var buttonId = e.target.id; var buttonId = e.target.id;
$("#" + buttonId).prop("disabled", true);
e.preventDefault();
var $form = $('#form' + buttonId); var $form = $('#form' + buttonId);
var data = $form.serialize(); var data = $form.serialize();
var seasons = $(this).attr("season-select"); var seasons = $(this).attr("season-select");
if (seasons === "1") { if (seasons === "1") {
// Send over the latest
data = data + "&latest=true"; data = data + "&latest=true";
} }
@ -39,14 +44,16 @@ $(document).on("click", ".dropdownTv", function (e) {
var url = $form.prop('action'); var url = $form.prop('action');
sendRequestAjax(data, type, url, buttonId); sendRequestAjax(data, type, url, buttonId);
$("#" + buttonId).prop("disabled", false);
}); });
// Click Request for movie // Click Request for movie
$(document).on("click", ".requestMovie", function (e) { $(document).on("click", ".requestMovie", function (e) {
$(".requestMovie").prop("disabled", true); var buttonId = e.target.id;
$("#" + buttonId).prop("disabled", true);
e.preventDefault(); e.preventDefault();
var buttonId = e.target.id;
var $form = $('#form' + buttonId); var $form = $('#form' + buttonId);
var type = $form.prop('method'); var type = $form.prop('method');
@ -54,6 +61,7 @@ $(document).on("click", ".requestMovie", function (e) {
var data = $form.serialize(); var data = $form.serialize();
sendRequestAjax(data, type, url, buttonId); sendRequestAjax(data, type, url, buttonId);
$("#" + buttonId).prop("disabled", false);
}); });
function sendRequestAjax(data, type, url, buttonId) { function sendRequestAjax(data, type, url, buttonId) {
@ -113,3 +121,34 @@ function tvSearch() {
}); });
}; };
function buildMovieContext(result) {
var date = new Date(result.releaseDate);
var year = date.getFullYear();
var context = {
posterPath: result.posterPath,
id: result.id,
title: result.title,
overview: result.overview,
voteCount: result.voteCount,
voteAverage: result.voteAverage,
year: year,
type: "movie"
};
return context;
}
function buildTvShowContext(result) {
var date = new Date(result.firstAired);
var year = date.getFullYear();
var context = {
posterPath: result.banner,
id: result.id,
title: result.seriesName,
overview: result.overview,
year: year,
type: "tv"
};
return context;
}

View file

@ -9,33 +9,11 @@
}); });
} }
function buildMovieContext(result) { function checkJsonResponse(response) {
var date = new Date(result.releaseDate); if (response.result === true) {
var year = date.getFullYear(); return true;
var context = { } else {
posterPath: result.posterPath, generateNotify(response.message, "warning");
id: result.id, return false;
title: result.title,
overview: result.overview,
voteCount: result.voteCount,
voteAverage: result.voteAverage,
year: year,
type: "movie"
};
return context;
} }
function buildTvShowContext(result) {
var date = new Date(result.firstAired);
var year = date.getFullYear();
var context = {
posterPath: result.banner,
id: result.id,
title: result.seriesName,
overview: result.overview,
year: year,
type: "tv"
};
return context;
} }

View file

@ -0,0 +1,34 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: JsonResponseModel.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
namespace PlexRequests.UI.Models
{
public class JsonResponseModel
{
public bool Result { get; set; }
public string Message { get; set; }
}
}

View file

@ -44,5 +44,6 @@ namespace PlexRequests.UI.Models
public string RequestedDate { get; set; } public string RequestedDate { get; set; }
public string ReleaseYear { get; set; } public string ReleaseYear { get; set; }
public bool Available { get; set; } public bool Available { get; set; }
public bool Admin { get; set; }
} }
} }

View file

@ -0,0 +1,120 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: ApprovalModule.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using Nancy;
using Nancy.Security;
using NLog;
using PlexRequests.Store;
using PlexRequests.UI.Models;
namespace PlexRequests.UI.Modules
{
public class ApprovalModule : BaseModule
{
public ApprovalModule(IRepository<RequestedModel> service) : base("approval")
{
this.RequiresAuthentication();
Service = service;
Post["/approve"] = parameters => Approve((int)Request.Form.requestid);
Post["/approveall"] = x => ApproveAll();
}
private IRepository<RequestedModel> Service { get; set; }
private static Logger Log = LogManager.GetCurrentClassLogger();
/// <summary>
/// Approves the specified request identifier.
/// </summary>
/// <param name="requestId">The request identifier.</param>
/// <returns></returns>
private Response Approve(int requestId)
{
// Get the request from the DB
var request = Service.Get(requestId);
if (request == null)
{
Log.Warn("Tried approving a request, but the request did not exist in the database, requestId = {0}", requestId);
return Response.AsJson(new JsonResponseModel { Result = false, Message = "There are no requests to approve. Please refresh." });
}
// Approve it
request.Approved = true;
// Update the record
var result = Service.Update(request);
return Response.AsJson(result
? new JsonResponseModel { Result = true }
: new JsonResponseModel { Result = false, Message = "We could not approve this request. Please try again or check the logs." });
}
/// <summary>
/// Approves all.
/// </summary>
/// <returns></returns>
private Response ApproveAll()
{
var requests = Service.GetAll();
var requestedModels = requests as RequestedModel[] ?? requests.ToArray();
if (!requestedModels.Any())
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "There are no requests to approve. Please refresh." });
}
var updatedRequests = new List<RequestedModel>();
foreach (var r in requestedModels)
{
r.Approved = true;
updatedRequests.Add(r);
}
try
{
var result = Service.UpdateAll(updatedRequests); return Response.AsJson(result
? new JsonResponseModel { Result = true }
: new JsonResponseModel { Result = false, Message = "We could not approve all of the requests. Please try again or check the logs." });
}
catch (Exception e)
{
Log.Fatal(e);
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Something bad happened, please check the logs!" });
}
}
}
}

View file

@ -32,6 +32,8 @@ using Humanizer;
using Nancy; using Nancy;
using Nancy.Responses.Negotiation; using Nancy.Responses.Negotiation;
using Nancy.Security;
using PlexRequests.Api; using PlexRequests.Api;
using PlexRequests.Core; using PlexRequests.Core;
using PlexRequests.Core.SettingModels; using PlexRequests.Core.SettingModels;
@ -67,11 +69,12 @@ namespace PlexRequests.UI.Modules
private Negotiator LoadRequests() private Negotiator LoadRequests()
{ {
var settings = PrSettings.GetSettings(); var settings = PrSettings.GetSettings();
return View["Requests/Index", settings]; return View["Index", settings];
} }
private Response GetMovies() private Response GetMovies()
{ {
var isAdmin = Context.CurrentUser.IsAuthenticated();
var dbMovies = Service.GetAll().Where(x => x.Type == RequestType.Movie); var dbMovies = Service.GetAll().Where(x => x.Type == RequestType.Movie);
var viewModel = dbMovies.Select(movie => new RequestViewModel var viewModel = dbMovies.Select(movie => new RequestViewModel
{ {
@ -88,7 +91,8 @@ namespace PlexRequests.UI.Modules
Overview = movie.Overview, Overview = movie.Overview,
RequestedBy = movie.RequestedBy, RequestedBy = movie.RequestedBy,
ReleaseYear = movie.ReleaseDate.Year.ToString(), ReleaseYear = movie.ReleaseDate.Year.ToString(),
Available = movie.Available Available = movie.Available,
Admin = isAdmin
}).ToList(); }).ToList();
return Response.AsJson(viewModel); return Response.AsJson(viewModel);
@ -96,6 +100,7 @@ namespace PlexRequests.UI.Modules
private Response GetTvShows() private Response GetTvShows()
{ {
var isAdmin = Context.CurrentUser.IsAuthenticated();
var dbTv = Service.GetAll().Where(x => x.Type == RequestType.TvShow); var dbTv = Service.GetAll().Where(x => x.Type == RequestType.TvShow);
var viewModel = dbTv.Select(tv => new RequestViewModel var viewModel = dbTv.Select(tv => new RequestViewModel
{ {
@ -112,17 +117,22 @@ namespace PlexRequests.UI.Modules
Overview = tv.Overview, Overview = tv.Overview,
RequestedBy = tv.RequestedBy, RequestedBy = tv.RequestedBy,
ReleaseYear = tv.ReleaseDate.Year.ToString(), ReleaseYear = tv.ReleaseDate.Year.ToString(),
Available = tv.Available Available = tv.Available,
Admin = isAdmin
}).ToList(); }).ToList();
return Response.AsJson(viewModel); return Response.AsJson(viewModel);
} }
private Response DeleteRequest(int providerId, RequestType type) private Response DeleteRequest(int providerId, RequestType type)
{
if (Context.CurrentUser.IsAuthenticated())
{ {
var currentEntity = Service.GetAll().FirstOrDefault(x => x.ProviderId == providerId && x.Type == type); var currentEntity = Service.GetAll().FirstOrDefault(x => x.ProviderId == providerId && x.Type == type);
Service.Delete(currentEntity); Service.Delete(currentEntity);
return Response.AsJson(new { Result = true }); return Response.AsJson(new JsonResponseModel { Result = true });
}
return Response.AsJson(new JsonResponseModel { Result = false, Message = "You are not an Admin, so you cannot delete any requests." });
} }
} }
} }

View file

@ -163,6 +163,7 @@
</Content> </Content>
<Compile Include="Jobs\PlexRegistry.cs" /> <Compile Include="Jobs\PlexRegistry.cs" />
<Compile Include="Jobs\PlexTaskFactory.cs" /> <Compile Include="Jobs\PlexTaskFactory.cs" />
<Compile Include="Models\JsonResponseModel.cs" />
<Compile Include="Models\PlexAuth.cs" /> <Compile Include="Models\PlexAuth.cs" />
<Compile Include="Models\RequestViewModel.cs" /> <Compile Include="Models\RequestViewModel.cs" />
<Compile Include="Models\SearchTvShowViewModel.cs" /> <Compile Include="Models\SearchTvShowViewModel.cs" />
@ -170,6 +171,7 @@
<Compile Include="Modules\AdminModule.cs" /> <Compile Include="Modules\AdminModule.cs" />
<Compile Include="Modules\BaseModule.cs" /> <Compile Include="Modules\BaseModule.cs" />
<Compile Include="Modules\IndexModule.cs" /> <Compile Include="Modules\IndexModule.cs" />
<Compile Include="Modules\ApprovalModule.cs" />
<Compile Include="Modules\UserLoginModule.cs" /> <Compile Include="Modules\UserLoginModule.cs" />
<Compile Include="Modules\LoginModule.cs" /> <Compile Include="Modules\LoginModule.cs" />
<Compile Include="Modules\RequestsModule.cs" /> <Compile Include="Modules\RequestsModule.cs" />
@ -217,9 +219,6 @@
<None Include="sqlite3.dll"> <None Include="sqlite3.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<Content Include="Views\Index.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="web.config"> <Content Include="web.config">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Content> </Content>

View file

@ -1,2 +0,0 @@
Home

View file

@ -1,6 +1,11 @@
<div> @using Nancy.Security
<div>
<h1>Requests</h1> <h1>Requests</h1>
<h4>Below you can see yours and all other requests, as well as their download and approval status.</h4> <h4>Below you can see yours and all other requests, as well as their download and approval status.</h4>
@if (Context.CurrentUser.IsAuthenticated())
{
<button id="approveAll" class="btn btn-primary" type="submit"><i class="fa fa-plus"></i> Approve All</button>
}
<!-- Nav tabs --> <!-- Nav tabs -->
<ul id="nav-tabs" class="nav nav-tabs" role="tablist"> <ul id="nav-tabs" class="nav nav-tabs" role="tablist">
@if (Model.SearchForMovies) @if (Model.SearchForMovies)
@ -92,11 +97,29 @@
<div class="col-sm-2 col-sm-push-3"> <div class="col-sm-2 col-sm-push-3">
<br /> <br />
<br /> <br />
{{#if_eq admin true}}
<form method="POST" action="/requests/delete" id="form{{id}}"> <form method="POST" action="/requests/delete" id="form{{id}}">
<input name="Id" type="text" value="{{id}}" hidden="hidden" /> <input name="Id" type="text" value="{{id}}" hidden="hidden" />
<input name="Type" type="text" value="{{type}}" hidden="hidden" /> <input name="Type" type="text" value="{{type}}" hidden="hidden" />
<button id="{{id}}" style="text-align: right" class="btn btn-danger delete" type="submit"><i class="fa fa-plus"></i> Remove</button> <button id="{{id}}" style="text-align: right" class="btn btn-danger delete" type="submit"><i class="fa fa-plus"></i> Remove</button>
</form> </form>
{{/if_eq}}
{{#if_eq admin false}}
<div class="dropdown">
<button id="{{id}}" class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<i class="fa fa-plus"></i> Report Issue
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li><a id="{{id}}" issue-select="0" class="dropdownIssue" href="#">Wrong Audio</a></li>
<li><a id="{{id}}" issue-select="1" class="dropdownIssue" href="#">No Subtitles</a></li>
<li><a id="{{id}}" issue-select="2" class="dropdownIssue" href="#">Wrong Content</a></li>
<li><a id="{{id}}" issue-select="3" class="dropdownIssue" href="#">Playback Issues</a></li>
<li><a id="{{id}}" issue-select="4" class="dropdownIssue" data-identifier="{{id}}" href="#" data-toggle="modal" data-target="#myModal">Other</a></li>
</ul>
</div>
{{/if_eq}}
</div> </div>
</div> </div>
@ -104,5 +127,22 @@
</div> </div>
</script> </script>
<div class="modal fade" id="myModal">
<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">Modal title</h4>
</div>
<div class="modal-body">
<p>One fine body</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary theSaveButton">Save changes</button>
</div>
</div>
</div>
</div>
<script src="/Content/requests.js" type="text/javascript"></script> <script src="/Content/requests.js" type="text/javascript"></script>