pull/332/head
tidusjar 9 years ago
parent 247ef4833a
commit ae4d51de9b

@ -33,21 +33,21 @@ namespace PlexRequests.Core
public const int SchedulerCaching = 60; public const int SchedulerCaching = 60;
} }
public const string PlexLibaries = "PlexLibaries"; public const string PlexLibaries = nameof(PlexLibaries);
public const string TvDbToken = "TheTvDbApiToken"; public const string TvDbToken = nameof(TvDbToken);
public const string SonarrQualityProfiles = "SonarrQualityProfiles"; public const string SonarrQualityProfiles = nameof(SonarrQualityProfiles);
public const string SonarrQueued = "SonarrQueued"; public const string SonarrQueued = nameof(SonarrQueued);
public const string SickRageQualityProfiles = "SickRageQualityProfiles"; public const string SickRageQualityProfiles = nameof(SickRageQualityProfiles);
public const string SickRageQueued = "SickRageQueued"; public const string SickRageQueued = nameof(SickRageQueued);
public const string CouchPotatoQualityProfiles = "CouchPotatoQualityProfiles"; public const string CouchPotatoQualityProfiles = nameof(CouchPotatoQualityProfiles);
public const string CouchPotatoQueued = "CouchPotatoQueued"; public const string CouchPotatoQueued = nameof(CouchPotatoQueued);
public const string GetPlexRequestSettings = "GetPlexRequestSettings"; public const string GetPlexRequestSettings = nameof(GetPlexRequestSettings);
public const string LastestProductVersion = "LatestProductVersion"; public const string LastestProductVersion = nameof(LastestProductVersion);
} }
} }

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

@ -0,0 +1,115 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: IssueJsonService.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using PlexRequests.Core.Models;
using PlexRequests.Helpers;
using PlexRequests.Store.Models;
using PlexRequests.Store.Repository;
namespace PlexRequests.Core
{
public class IssueJsonService : IIssueService
{
public IssueJsonService(IRepository<IssueBlobs> repo)
{
Repo = repo;
}
private IRepository<IssueBlobs> Repo { get; }
public async Task<int> AddIssueAsync(IssuesModel model)
{
var entity = new IssueBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), RequestId = model.RequestId };
var id = await Repo.InsertAsync(entity);
model.Id = id;
entity = new IssueBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), RequestId = model.RequestId, Id = id };
var result = await Repo.UpdateAsync(entity);
return result ? id : -1;
}
public async Task<bool> UpdateIssueAsync(IssuesModel model)
{
var entity = new IssueBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), RequestId = model.RequestId, Id = model.Id };
return await Repo.UpdateAsync(entity);
}
public async Task DeleteIssueAsync(int id)
{
var entity = await Repo.GetAsync(id);
await Repo.DeleteAsync(entity);
}
public async Task DeleteIssueAsync(IssuesModel model)
{
var entity = new IssueBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), RequestId = model.RequestId, Id = model.Id };
await Repo.DeleteAsync(entity);
}
/// <summary>
/// Gets the Issues, if there is no issue in the DB we return a <c>new <see cref="IssuesModel"/></c>.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns></returns>
public async Task<IssuesModel> GetAsync(int id)
{
var blob = await Repo.GetAsync(id);
if (blob == null)
{
return new IssuesModel();
}
var model = ByteConverterHelper.ReturnObject<IssuesModel>(blob.Content);
return model;
}
/// <summary>
/// Gets all the Issues, if there is no issue in the DB we return a <c>new IEnumerable&lt;IssuesModel&gt;</c>.
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<IssuesModel>> GetAllAsync()
{
var blobs = await Repo.GetAllAsync();
if (blobs == null)
{
return new List<IssuesModel>();
}
return blobs.Select(b => Encoding.UTF8.GetString(b.Content))
.Select(JsonConvert.DeserializeObject<IssuesModel>)
.ToList();
}
}
}

@ -1,7 +1,7 @@
#region Copyright #region Copyright
// /************************************************************************ // /************************************************************************
// Copyright (c) 2016 Jamie Rees // Copyright (c) 2016 Jamie Rees
// File: JsonRequestService.cs // File: JsonRequestModelRequestService.cs
// Created By: Jamie Rees // Created By: Jamie Rees
// //
// Permission is hereby granted, free of charge, to any person obtaining // Permission is hereby granted, free of charge, to any person obtaining
@ -38,9 +38,9 @@ using PlexRequests.Store.Repository;
namespace PlexRequests.Core namespace PlexRequests.Core
{ {
public class JsonRequestService : IRequestService public class JsonRequestModelRequestService : IRequestService
{ {
public JsonRequestService(IRequestRepository repo) public JsonRequestModelRequestService(IRequestRepository repo)
{ {
Repo = repo; Repo = repo;
} }

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

@ -66,9 +66,12 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="CacheKeys.cs" /> <Compile Include="CacheKeys.cs" />
<Compile Include="IIssueService.cs" />
<Compile Include="IRequestService.cs" /> <Compile Include="IRequestService.cs" />
<Compile Include="ISettingsService.cs" /> <Compile Include="ISettingsService.cs" />
<Compile Include="JsonRequestService.cs" /> <Compile Include="JsonIssuesModelRequestService.cs" />
<Compile Include="JsonRequestModelRequestService.cs" />
<Compile Include="Models\IssuesModel.cs" />
<Compile Include="Models\StatusModel.cs" /> <Compile Include="Models\StatusModel.cs" />
<Compile Include="Models\UserProperties.cs" /> <Compile Include="Models\UserProperties.cs" />
<Compile Include="SettingModels\AuthenticationSettings.cs" /> <Compile Include="SettingModels\AuthenticationSettings.cs" />

@ -0,0 +1,38 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: RequestBlobs.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 Dapper.Contrib.Extensions;
namespace PlexRequests.Store.Models
{
[Table("IssueBlobs")]
public class IssueBlobs : Entity
{
public int RequestId { get; set; }
public byte[] Content { get; set; }
public RequestType Type { get; set; }
}
}

@ -62,6 +62,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="DbConfiguration.cs" /> <Compile Include="DbConfiguration.cs" />
<Compile Include="Entity.cs" /> <Compile Include="Entity.cs" />
<Compile Include="Models\IssueBlobs.cs" />
<Compile Include="Models\ScheduledJobs.cs" /> <Compile Include="Models\ScheduledJobs.cs" />
<Compile Include="Models\UsersToNotify.cs" /> <Compile Include="Models\UsersToNotify.cs" />
<Compile Include="Repository\BaseGenericRepository.cs" /> <Compile Include="Repository\BaseGenericRepository.cs" />

@ -73,3 +73,12 @@ CREATE TABLE IF NOT EXISTS UsersToNotify
Username varchar(100) NOT NULL Username varchar(100) NOT NULL
); );
CREATE UNIQUE INDEX IF NOT EXISTS UsersToNotify_Id ON UsersToNotify (Id); CREATE UNIQUE INDEX IF NOT EXISTS UsersToNotify_Id ON UsersToNotify (Id);
CREATE TABLE IF NOT EXISTS IssueBlobs
(
Id INTEGER PRIMARY KEY AUTOINCREMENT,
RequestId INTEGER,
Type INTEGER NOT NULL,
Content BLOB NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS IssueBlobs_Id ON IssueBlobs (Id);

@ -68,9 +68,6 @@ namespace PlexRequests.UI
protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context) protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context)
{ {
container.Register<ICacheProvider, MemoryCacheProvider>().AsSingleton();
// Settings // Settings
container.Register<ISettingsService<PlexRequestSettings>, SettingsServiceV2<PlexRequestSettings>>(); container.Register<ISettingsService<PlexRequestSettings>, SettingsServiceV2<PlexRequestSettings>>();
container.Register<ISettingsService<CouchPotatoSettings>, SettingsServiceV2<CouchPotatoSettings>>(); container.Register<ISettingsService<CouchPotatoSettings>, SettingsServiceV2<CouchPotatoSettings>>();
@ -89,7 +86,9 @@ namespace PlexRequests.UI
container.Register<IRepository<LogEntity>, GenericRepository<LogEntity>>(); container.Register<IRepository<LogEntity>, GenericRepository<LogEntity>>();
container.Register<IRepository<UsersToNotify>, GenericRepository<UsersToNotify>>(); container.Register<IRepository<UsersToNotify>, GenericRepository<UsersToNotify>>();
container.Register<IRepository<ScheduledJobs>, GenericRepository<ScheduledJobs>>(); container.Register<IRepository<ScheduledJobs>, GenericRepository<ScheduledJobs>>();
container.Register<IRequestService, JsonRequestService>(); container.Register<IRepository<IssueBlobs>, GenericRepository<IssueBlobs>>();
container.Register<IRequestService, JsonRequestModelRequestService>();
container.Register<IIssueService, IssueJsonService>();
container.Register<ISettingsRepository, SettingsJsonRepository>(); container.Register<ISettingsRepository, SettingsJsonRepository>();
container.Register<IJobRecord, JobRecord>(); container.Register<IJobRecord, JobRecord>();
@ -100,7 +99,7 @@ namespace PlexRequests.UI
container.Register<ISickRageCacher, SickRageCacher>(); container.Register<ISickRageCacher, SickRageCacher>();
container.Register<IJobFactory, CustomJobFactory>(); container.Register<IJobFactory, CustomJobFactory>();
// Api's // Api
container.Register<ICouchPotatoApi, CouchPotatoApi>(); container.Register<ICouchPotatoApi, CouchPotatoApi>();
container.Register<IPushbulletApi, PushbulletApi>(); container.Register<IPushbulletApi, PushbulletApi>();
container.Register<IPushoverApi, PushoverApi>(); container.Register<IPushoverApi, PushoverApi>();
@ -125,6 +124,7 @@ namespace PlexRequests.UI
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines) protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{ {
container.Register<ICacheProvider, MemoryCacheProvider>().AsSingleton();
container.Register<ISqliteConfiguration, DbConfiguration>(new DbConfiguration(new SqliteFactory())); container.Register<ISqliteConfiguration, DbConfiguration>(new DbConfiguration(new SqliteFactory()));
container.Register<IRepository<UsersModel>, UserRepository<UsersModel>>(); container.Register<IRepository<UsersModel>, UserRepository<UsersModel>>();
container.Register<IUserMapper, UserMapper>(); container.Register<IUserMapper, UserMapper>();
@ -132,7 +132,6 @@ namespace PlexRequests.UI
CookieBasedSessions.Enable(pipelines, CryptographyConfiguration.Default); CookieBasedSessions.Enable(pipelines, CryptographyConfiguration.Default);
StaticConfiguration.DisableErrorTraces = false; StaticConfiguration.DisableErrorTraces = false;
base.ApplicationStartup(container, pipelines); base.ApplicationStartup(container, pipelines);

@ -157,6 +157,27 @@ namespace PlexRequests.UI.Helpers
return helper.Raw(returnString); return helper.Raw(returnString);
} }
public static IHtmlString GetNavbarUrl(this HtmlHelpers helper, NancyContext context, string url, string title, string fontIcon, string extraHtml)
{
var returnString = string.Empty;
var content = GetLinkUrl(GetBaseUrl());
if (!string.IsNullOrEmpty(content))
{
url = $"/{content}{url}";
}
if (context.Request.Path == url)
{
returnString = $"<li class=\"active\"><a href=\"{url}\"><i class=\"fa fa-{fontIcon}\"></i> {title} {extraHtml}</a></li>";
}
else
{
returnString = $"<li><a href=\"{url}\"><i class=\"fa fa-{fontIcon}\"></i> {title} {extraHtml}</a></li>";
}
return helper.Raw(returnString);
}
public static IHtmlString GetBaseUrl(this HtmlHelpers helper) public static IHtmlString GetBaseUrl(this HtmlHelpers helper)
{ {
return helper.Raw(GetBaseUrl()); return helper.Raw(GetBaseUrl());

@ -0,0 +1,51 @@
using System.Linq;
using System.Threading.Tasks;
using Nancy;
using Nancy.Responses.Negotiation;
using PlexRequests.Core;
using PlexRequests.Core.SettingModels;
namespace PlexRequests.UI.Modules
{
public class IssuesModule : BaseAuthModule
{
public IssuesModule(ISettingsService<PlexRequestSettings> pr, IIssueService issueService) : base("issues", pr)
{
IssuesService = issueService;
Get["/"] = x => Index();
Get["/issuecount", true] = async (x, ct) => await IssueCount();
Get["/details/{id}", true] = async (x, ct) => await Details(x.id);
}
private IIssueService IssuesService { get; }
public Negotiator Index()
{
return View["Index"];
}
public async Task<Response> IssueCount()
{
var issues = await IssuesService.GetAllAsync();
var count = issues.Count(x => x.Deleted == false);
return Response.AsJson(count);
}
public async Task<Negotiator> Details(int id)
{
var issue = await IssuesService.GetAsync(id);
return issue == null
? Index()
: View["Details", issue];
}
}
}

@ -190,6 +190,7 @@
<Compile Include="Modules\ApiUserModule.cs" /> <Compile Include="Modules\ApiUserModule.cs" />
<Compile Include="Modules\BaseApiModule.cs" /> <Compile Include="Modules\BaseApiModule.cs" />
<Compile Include="Modules\BaseModule.cs" /> <Compile Include="Modules\BaseModule.cs" />
<Compile Include="Modules\IssuesModule.cs" />
<Compile Include="Modules\UpdateCheckerModule.cs" /> <Compile Include="Modules\UpdateCheckerModule.cs" />
<Compile Include="Start\StartupOptions.cs" /> <Compile Include="Start\StartupOptions.cs" />
<Compile Include="Start\UpdateValue.cs" /> <Compile Include="Start\UpdateValue.cs" />

@ -39,6 +39,8 @@
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
@Html.GetNavbarUrl(Context, "/search", "Search", "search") @Html.GetNavbarUrl(Context, "/search", "Search", "search")
@Html.GetNavbarUrl(Context, "/requests", "Requests", "plus-circle") @Html.GetNavbarUrl(Context, "/requests", "Requests", "plus-circle")
@Html.GetNavbarUrl(Context, "/issues", "Issues", "exclamation", "<span id=\"issueCount\" class=\"badge\">0</span>")
</ul> </ul>
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
@ -87,6 +89,8 @@
$(function () { $(function () {
var urlBase = '@Html.GetBaseUrl()'; var urlBase = '@Html.GetBaseUrl()';
// Check for update
var url = createBaseUrl(urlBase, '/updatechecker'); var url = createBaseUrl(urlBase, '/updatechecker');
$.ajax({ $.ajax({
type: "GET", type: "GET",
@ -97,14 +101,17 @@
var status = createBaseUrl(urlBase, '/admin/status'); var status = createBaseUrl(urlBase, '/admin/status');
$('#updateAvailable').html("<i class='fa fa-cloud-download' aria-hidden='true'></i> There is a new update available! Click <a style='color: white' href='" + status + "'>Here!</a>"); $('#updateAvailable').html("<i class='fa fa-cloud-download' aria-hidden='true'></i> There is a new update available! Click <a style='color: white' href='" + status + "'>Here!</a>");
$('#updateAvailable').removeAttr("hidden"); $('#updateAvailable').removeAttr("hidden");
$('body').addClass('update-available') $('body').addClass('update-available');
} }
}, },
error: function (e) { error: function (e) {
console.log(e); console.log(e);
} }
}); });
// End Check for update
// Scroller
$(document).on('scroll', function () { $(document).on('scroll', function () {
if ($(window).scrollTop() > 100) { if ($(window).scrollTop() > 100) {
@ -115,6 +122,27 @@
}); });
$('.scroll-top-wrapper').on('click', scrollToTop); $('.scroll-top-wrapper').on('click', scrollToTop);
// End Scroller
// Get Issue count
var issueUrl = createBaseUrl(urlBase, '/issues/issuecount');
$.ajax({
type: "GET",
url: issueUrl,
dataType: "json",
success: function (response) {
if (response) {
$('#issueCount').html(response);
}
},
error: function (e) {
console.log(e);
}
});
// End issue count
}); });
function scrollToTop() { function scrollToTop() {

Loading…
Cancel
Save