diff --git a/PlexRequests.Core/PlexRequests.Core.csproj b/PlexRequests.Core/PlexRequests.Core.csproj index 8163e940a..495a09ed8 100644 --- a/PlexRequests.Core/PlexRequests.Core.csproj +++ b/PlexRequests.Core/PlexRequests.Core.csproj @@ -78,6 +78,7 @@ + diff --git a/PlexRequests.Core/SettingModels/ScheduledJobsSettings.cs b/PlexRequests.Core/SettingModels/ScheduledJobsSettings.cs new file mode 100644 index 000000000..216f54f88 --- /dev/null +++ b/PlexRequests.Core/SettingModels/ScheduledJobsSettings.cs @@ -0,0 +1,47 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ScheduledJobsSettings.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.Core.SettingModels +{ + public class ScheduledJobsSettings : Settings + { + public ScheduledJobsSettings() + { + PlexAvailabilityChecker = 10; + SickRageCacher = 10; + SonarrCacher = 10; + CouchPotatoCacher = 10; + StoreBackup = 24; + StoreCleanup = 24; + } + public int PlexAvailabilityChecker { get; set; } + public int SickRageCacher { get; set; } + public int SonarrCacher { get; set; } + public int CouchPotatoCacher { get; set; } + public int StoreBackup { get; set; } + public int StoreCleanup { get; set; } + } +} \ No newline at end of file diff --git a/PlexRequests.Helpers.Tests/DateTimeHelperTests.cs b/PlexRequests.Helpers.Tests/DateTimeHelperTests.cs new file mode 100644 index 000000000..b327f1259 --- /dev/null +++ b/PlexRequests.Helpers.Tests/DateTimeHelperTests.cs @@ -0,0 +1,54 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: DateTimeHelperTests.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 NUnit.Framework; + +namespace PlexRequests.Helpers.Tests +{ + [TestFixture] + public class DateTimeHelperTests + { + [TestCaseSource(nameof(OffsetUtcDateTimeData))] + public DateTime TestOffsetUtcDateTimeData(DateTime utcDateTime, int minuteOffset) + { + var offset = DateTimeHelper.OffsetUTCDateTime(utcDateTime, minuteOffset); + return offset.DateTime; + } + + private static IEnumerable OffsetUtcDateTimeData + { + get + { + yield return new TestCaseData(new DateTime(2016,01,01,12,00,00), -60).Returns(new DateTimeOffset(new DateTime(2016, 01, 01, 13, 00, 00)).DateTime); + yield return new TestCaseData(new DateTime(2016,01,01,12,00,00), -120).Returns(new DateTimeOffset(new DateTime(2016, 01, 01, 14, 00, 00)).DateTime); + yield return new TestCaseData(new DateTime(2016,01,01,12,00,00), 120).Returns(new DateTimeOffset(new DateTime(2016, 01, 01, 10, 00, 00)).DateTime); + } + } + } +} \ No newline at end of file diff --git a/PlexRequests.Helpers.Tests/PlexRequests.Helpers.Tests.csproj b/PlexRequests.Helpers.Tests/PlexRequests.Helpers.Tests.csproj index 9129651fb..308e966e7 100644 --- a/PlexRequests.Helpers.Tests/PlexRequests.Helpers.Tests.csproj +++ b/PlexRequests.Helpers.Tests/PlexRequests.Helpers.Tests.csproj @@ -71,6 +71,7 @@ + diff --git a/PlexRequests.Services/Interfaces/IJobRecord.cs b/PlexRequests.Services/Interfaces/IJobRecord.cs index 66c3be88c..da6bc6b3f 100644 --- a/PlexRequests.Services/Interfaces/IJobRecord.cs +++ b/PlexRequests.Services/Interfaces/IJobRecord.cs @@ -24,10 +24,17 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ************************************************************************/ #endregion +using System.Collections.Generic; +using System.Threading.Tasks; + +using PlexRequests.Store.Models; + namespace PlexRequests.Services.Interfaces { public interface IJobRecord { void Record(string jobName); + Task> GetJobsAsync(); + IEnumerable GetJobs(); } } \ No newline at end of file diff --git a/PlexRequests.Services/Jobs/JobRecord.cs b/PlexRequests.Services/Jobs/JobRecord.cs index fd97f785f..3538a7b0b 100644 --- a/PlexRequests.Services/Jobs/JobRecord.cs +++ b/PlexRequests.Services/Jobs/JobRecord.cs @@ -25,13 +25,15 @@ // ************************************************************************/ #endregion using System; +using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using PlexRequests.Services.Interfaces; using PlexRequests.Store.Models; using PlexRequests.Store.Repository; -namespace PlexRequests.Services +namespace PlexRequests.Services.Jobs { public class JobRecord : IJobRecord { @@ -39,7 +41,9 @@ namespace PlexRequests.Services { Repo = repo; } + private IRepository Repo { get; } + public void Record(string jobName) { var allJobs = Repo.GetAll(); @@ -55,5 +59,15 @@ namespace PlexRequests.Services Repo.Insert(job); } } + + public async Task> GetJobsAsync() + { + return await Repo.GetAllAsync(); + } + + public IEnumerable GetJobs() + { + return Repo.GetAll(); + } } } \ No newline at end of file diff --git a/PlexRequests.UI.Tests/AdminModuleTests.cs b/PlexRequests.UI.Tests/AdminModuleTests.cs index fdef0f6ca..66245d649 100644 --- a/PlexRequests.UI.Tests/AdminModuleTests.cs +++ b/PlexRequests.UI.Tests/AdminModuleTests.cs @@ -60,6 +60,7 @@ namespace PlexRequests.UI.Tests private Mock> PlexSettingsMock { get; set; } private Mock> SonarrSettingsMock { get; set; } private Mock> SickRageSettingsMock { get; set; } + private Mock> ScheduledJobsSettingsMock { get; set; } private Mock> EmailMock { get; set; } private Mock> PushbulletSettings { get; set; } private Mock> PushoverSettings { get; set; } @@ -69,6 +70,7 @@ namespace PlexRequests.UI.Tests private Mock PushbulletApi { get; set; } private Mock PushoverApi { get; set; } private Mock CpApi { get; set; } + private Mock RecorderMock { get; set; } private Mock> LogRepo { get; set; } private Mock NotificationService { get; set; } private Mock Cache { get; set; } @@ -111,6 +113,8 @@ namespace PlexRequests.UI.Tests SlackApi = new Mock(); SlackSettings = new Mock>(); LandingPageSettings = new Mock>(); + ScheduledJobsSettingsMock = new Mock>(); + RecorderMock = new Mock(); Bootstrapper = new ConfigurableBootstrapper(with => @@ -138,6 +142,8 @@ namespace PlexRequests.UI.Tests with.Dependency(SlackApi.Object); with.Dependency(LandingPageSettings.Object); with.Dependency(SlackSettings.Object); + with.Dependency(ScheduledJobsSettingsMock.Object); + with.Dependency(RecorderMock.Object); with.RootPathProvider(); with.RequestStartup((container, pipelines, context) => { diff --git a/PlexRequests.UI.Tests/LandingPageTests.cs b/PlexRequests.UI.Tests/LandingPageTests.cs index 59451379c..8789519ee 100644 --- a/PlexRequests.UI.Tests/LandingPageTests.cs +++ b/PlexRequests.UI.Tests/LandingPageTests.cs @@ -39,7 +39,7 @@ namespace PlexRequests.UI.Tests [TestCaseSource(nameof(NoticeEnabledData))] public bool TestNoticeEnabled(DateTime start, DateTime end) { - return new LandingPageViewModel {NoticeEnd = end, NoticeStart = start}.NoticeActive; + return new LandingPageViewModel { NoticeEnd = end, NoticeStart = start }.NoticeActive; } private static IEnumerable NoticeEnabledData diff --git a/PlexRequests.UI/Bootstrapper.cs b/PlexRequests.UI/Bootstrapper.cs index 5cfef5ca7..176404b02 100644 --- a/PlexRequests.UI/Bootstrapper.cs +++ b/PlexRequests.UI/Bootstrapper.cs @@ -56,6 +56,8 @@ using PlexRequests.Helpers.Analytics; using PlexRequests.Services.Jobs; using PlexRequests.UI.Jobs; +using Quartz; +using Quartz.Impl; using Quartz.Spi; namespace PlexRequests.UI @@ -170,6 +172,7 @@ namespace PlexRequests.UI container.Register, SettingsServiceV2>(); container.Register, SettingsServiceV2>(); container.Register, SettingsServiceV2>(); + container.Register, SettingsServiceV2>(); // Notification Service container.Register().AsSingleton(); @@ -203,6 +206,9 @@ namespace PlexRequests.UI container.Register(); container.Register(); + container.Register(); + container.Register(); + // Api container.Register(); diff --git a/PlexRequests.UI/Content/site-1.7.js b/PlexRequests.UI/Content/site-1.7.js index 53bec3d7f..13b81ddde 100644 --- a/PlexRequests.UI/Content/site-1.7.js +++ b/PlexRequests.UI/Content/site-1.7.js @@ -14,6 +14,10 @@ function Humanize(date) { return moment.duration(mNow - mDate).humanize() + (mNow.isBefore(mDate) ? ' from now' : ' ago'); } +function utcToLocal(date) { + return moment(date).local(); +} + function generateNotify(message, type) { // type = danger, warning, info, successs $.notify({ diff --git a/PlexRequests.UI/Jobs/Scheduler.cs b/PlexRequests.UI/Jobs/Scheduler.cs index 63ffe8b64..dc17a07d5 100644 --- a/PlexRequests.UI/Jobs/Scheduler.cs +++ b/PlexRequests.UI/Jobs/Scheduler.cs @@ -30,16 +30,20 @@ using System.Linq; using NLog; +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; using PlexRequests.Services.Jobs; +using PlexRequests.UI.Helpers; using Quartz; using Quartz.Impl; namespace PlexRequests.UI.Jobs { - internal sealed class Scheduler + internal sealed class Scheduler : IJobScheduler { private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + private IServiceLocator Service => ServiceLocator.Instance; private readonly ISchedulerFactory _factory; @@ -99,48 +103,51 @@ namespace PlexRequests.UI.Jobs private IEnumerable CreateTriggers() { + var settingsService = Service.Resolve>(); + var s = settingsService.GetSettings(); + var triggers = new List(); var plexAvailabilityChecker = TriggerBuilder.Create() .WithIdentity("PlexAvailabilityChecker", "Plex") .StartNow() - .WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever()) + .WithSimpleSchedule(x => x.WithIntervalInMinutes(s.PlexAvailabilityChecker).RepeatForever()) .Build(); var srCacher = TriggerBuilder.Create() .WithIdentity("SickRageCacher", "Cache") .StartNow() - .WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever()) + .WithSimpleSchedule(x => x.WithIntervalInMinutes(s.SickRageCacher).RepeatForever()) .Build(); var sonarrCacher = TriggerBuilder.Create() .WithIdentity("SonarrCacher", "Cache") .StartNow() - .WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever()) + .WithSimpleSchedule(x => x.WithIntervalInMinutes(s.SonarrCacher).RepeatForever()) .Build(); var cpCacher = TriggerBuilder.Create() .WithIdentity("CouchPotatoCacher", "Cache") .StartNow() - .WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever()) + .WithSimpleSchedule(x => x.WithIntervalInMinutes(s.CouchPotatoCacher).RepeatForever()) .Build(); var storeBackup = TriggerBuilder.Create() .WithIdentity("StoreBackup", "Database") .StartNow() - .WithSimpleSchedule(x => x.WithIntervalInHours(24).RepeatForever()) + .WithSimpleSchedule(x => x.WithIntervalInHours(s.StoreBackup).RepeatForever()) .Build(); var storeCleanup = TriggerBuilder.Create() .WithIdentity("StoreCleanup", "Database") .StartNow() - .WithSimpleSchedule(x => x.WithIntervalInHours(24).RepeatForever()) + .WithSimpleSchedule(x => x.WithIntervalInHours(s.StoreCleanup).RepeatForever()) .Build(); @@ -154,4 +161,9 @@ namespace PlexRequests.UI.Jobs return triggers; } } + + public interface IJobScheduler + { + void StartScheduler(); + } } \ No newline at end of file diff --git a/PlexRequests.UI/Models/ScheduledJobsViewModel.cs b/PlexRequests.UI/Models/ScheduledJobsViewModel.cs new file mode 100644 index 000000000..da444bd6f --- /dev/null +++ b/PlexRequests.UI/Models/ScheduledJobsViewModel.cs @@ -0,0 +1,38 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ScheduledJobsViewModel.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 PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.Models +{ + public class ScheduledJobsViewModel : ScheduledJobsSettings + { + public Dictionary JobRecorder { get; set; } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/AdminModule.cs b/PlexRequests.UI/Modules/AdminModule.cs index 7414e6b01..daf5f0967 100644 --- a/PlexRequests.UI/Modules/AdminModule.cs +++ b/PlexRequests.UI/Modules/AdminModule.cs @@ -86,7 +86,9 @@ namespace PlexRequests.UI.Modules private ICacheProvider Cache { get; } private ISettingsService SlackSettings { get; } private ISettingsService LandingSettings { get; } + private ISettingsService ScheduledJobSettings { get; } private ISlackApi SlackApi { get; } + private IJobRecord JobRecorder { get; } private static Logger Log = LogManager.GetCurrentClassLogger(); public AdminModule(ISettingsService prService, @@ -108,7 +110,8 @@ namespace PlexRequests.UI.Modules ISettingsService headphones, ISettingsService logs, ICacheProvider cache, ISettingsService slackSettings, - ISlackApi slackApi, ISettingsService lp) : base("admin", prService) + ISlackApi slackApi, ISettingsService lp, + ISettingsService scheduler, IJobRecord rec) : base("admin", prService) { PrService = prService; CpService = cpService; @@ -132,6 +135,8 @@ namespace PlexRequests.UI.Modules SlackSettings = slackSettings; SlackApi = slackApi; LandingSettings = lp; + ScheduledJobSettings = scheduler; + JobRecorder = rec; this.RequiresClaims(UserClaims.Admin); @@ -193,6 +198,9 @@ namespace PlexRequests.UI.Modules Get["/landingpage", true] = async (x, ct) => await LandingPage(); Post["/landingpage", true] = async (x, ct) => await SaveLandingPage(); + + Get["/scheduledjobs", true] = async (x, ct) => await GetScheduledJobs(); + Post["/scheduledjobs", true] = async (x, ct) => await SaveScheduledJobs(); } private async Task Authentication() @@ -835,5 +843,34 @@ namespace PlexRequests.UI.Modules ? new JsonResponseModel { Result = true } : new JsonResponseModel { Result = false, Message = "Could not save to Db Please check the logs" }); } + + private async Task GetScheduledJobs() + { + var s = await ScheduledJobSettings.GetSettingsAsync(); + var allJobs = await JobRecorder.GetJobsAsync(); + var jobsDict = allJobs.ToDictionary(k => k.Name, v => v.LastRun); + var model = new ScheduledJobsViewModel + { + CouchPotatoCacher = s.CouchPotatoCacher, + PlexAvailabilityChecker = s.PlexAvailabilityChecker, + SickRageCacher = s.SickRageCacher, + SonarrCacher = s.SonarrCacher, + StoreBackup = s.StoreBackup, + StoreCleanup = s.StoreCleanup, + JobRecorder = jobsDict + }; + return View["SchedulerSettings", model]; + } + + private async Task SaveScheduledJobs() + { + var settings = this.Bind(); + + var result = await ScheduledJobSettings.SaveSettingsAsync(settings); + + return Response.AsJson(result + ? new JsonResponseModel { Result = true } + : new JsonResponseModel { Result = false, Message = "Could not save to Db Please check the logs" }); + } } } \ No newline at end of file diff --git a/PlexRequests.UI/Modules/BaseAuthModule.cs b/PlexRequests.UI/Modules/BaseAuthModule.cs index 4ea42904a..4fbc0e096 100644 --- a/PlexRequests.UI/Modules/BaseAuthModule.cs +++ b/PlexRequests.UI/Modules/BaseAuthModule.cs @@ -23,64 +23,19 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ************************************************************************/ -using System.Linq; - #endregion using Nancy; using Nancy.Extensions; using PlexRequests.UI.Models; -using System; - using PlexRequests.Core; using PlexRequests.Core.SettingModels; -using PlexRequests.Helpers; namespace PlexRequests.UI.Modules { public abstract class BaseAuthModule : BaseModule { - private string _username; - private int _dateTimeOffset = -1; - - protected string Username - { - get - { - if (string.IsNullOrEmpty(_username)) - { - _username = Session[SessionKeys.UsernameKey].ToString(); - } - return _username; - } - } - - protected bool IsAdmin - { - get - { - if (Context.CurrentUser == null) - { - return false; - } - var claims = Context.CurrentUser.Claims.ToList(); - return claims.Contains(UserClaims.Admin) || claims.Contains(UserClaims.PowerUser); - } - } - - protected int DateTimeOffset - { - get - { - if (_dateTimeOffset == -1) - { - _dateTimeOffset = (int?)Session[SessionKeys.ClientDateTimeOffsetKey] ?? new DateTimeOffset().Offset.Minutes; - } - return _dateTimeOffset; - } - } - protected BaseAuthModule(ISettingsService pr) : base(pr) { PlexRequestSettings = pr; @@ -101,7 +56,7 @@ namespace PlexRequests.UI.Modules var baseUrl = settings.BaseUrl; var redirectPath = string.IsNullOrEmpty(baseUrl) ? "~/userlogin" : $"~/{baseUrl}/userlogin"; - + return Session[SessionKeys.UsernameKey] == null ? Context.GetRedirect(redirectPath) : null; diff --git a/PlexRequests.UI/Modules/BaseModule.cs b/PlexRequests.UI/Modules/BaseModule.cs index 335fc16f5..2ebce8fa7 100644 --- a/PlexRequests.UI/Modules/BaseModule.cs +++ b/PlexRequests.UI/Modules/BaseModule.cs @@ -24,10 +24,15 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ************************************************************************/ #endregion +using System; +using System.Linq; + using Nancy; using PlexRequests.Core; using PlexRequests.Core.SettingModels; +using PlexRequests.Helpers; +using PlexRequests.UI.Models; namespace PlexRequests.UI.Modules { @@ -56,5 +61,45 @@ namespace PlexRequests.UI.Modules ModulePath = settingModulePath; } + + private int _dateTimeOffset = -1; + protected int DateTimeOffset + { + get + { + if (_dateTimeOffset == -1) + { + _dateTimeOffset = (int?)Session[SessionKeys.ClientDateTimeOffsetKey] ?? new DateTimeOffset().Offset.Minutes; + } + return _dateTimeOffset; + } + } + private string _username; + + protected string Username + { + get + { + if (string.IsNullOrEmpty(_username)) + { + _username = Session[SessionKeys.UsernameKey].ToString(); + } + return _username; + } + } + + protected bool IsAdmin + { + get + { + if (Context.CurrentUser == null) + { + return false; + } + var claims = Context.CurrentUser.Claims.ToList(); + return claims.Contains(UserClaims.Admin) || claims.Contains(UserClaims.PowerUser); + } + } + } } \ No newline at end of file diff --git a/PlexRequests.UI/PlexRequests.UI.csproj b/PlexRequests.UI/PlexRequests.UI.csproj index a401877e2..30442e1a8 100644 --- a/PlexRequests.UI/PlexRequests.UI.csproj +++ b/PlexRequests.UI/PlexRequests.UI.csproj @@ -182,6 +182,7 @@ + @@ -557,6 +558,9 @@ Always + + Always + web.config diff --git a/PlexRequests.UI/Startup.cs b/PlexRequests.UI/Startup.cs index a4a3c81cf..14aa38657 100644 --- a/PlexRequests.UI/Startup.cs +++ b/PlexRequests.UI/Startup.cs @@ -26,10 +26,13 @@ #endregion using System; +using Nancy.TinyIoc; + using NLog; using Owin; +using PlexRequests.UI.Helpers; using PlexRequests.UI.Jobs; namespace PlexRequests.UI @@ -43,7 +46,6 @@ namespace PlexRequests.UI try { app.UseNancy(); - var scheduler = new Scheduler(); scheduler.StartScheduler(); } diff --git a/PlexRequests.UI/Views/Admin/SchedulerSettings.cshtml b/PlexRequests.UI/Views/Admin/SchedulerSettings.cshtml new file mode 100644 index 000000000..37e85e772 --- /dev/null +++ b/PlexRequests.UI/Views/Admin/SchedulerSettings.cshtml @@ -0,0 +1,109 @@ +@using PlexRequests.UI.Helpers +@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase +@Html.Partial("_Sidebar") + + + + + + Job Name + Last Run + + @foreach (var record in Model.JobRecorder) + { + + @record.Key + @record.Value.ToString("O") + + } + + + + + Scheduler Settings + Please note, you will need to restart for these settings to take effect + + + Plex Availability Checker (min) + + + + + Couch Potato Cacher (min) + + + + + + Sonarr Cacher (min) + + + + + + + SickRage Cacher (min) + + + + + + + Store Backup (hour) + + + + + + + Store Cleanup (hour) + + + + + + + Submit + + + + + + \ No newline at end of file