pull/332/head
tidusjar 9 years ago
parent e8706354b9
commit 3e16d8acf0

@ -78,6 +78,7 @@
<Compile Include="SettingModels\AuthenticationSettings.cs" />
<Compile Include="SettingModels\HeadphonesSettings.cs" />
<Compile Include="SettingModels\LandingPageSettings.cs" />
<Compile Include="SettingModels\ScheduledJobsSettings.cs" />
<Compile Include="SettingModels\SlackNotificationSettings.cs" />
<Compile Include="SettingModels\PushoverNotificationSettings.cs" />
<Compile Include="SettingModels\PushBulletNotificationSettings.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; }
}
}

@ -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<TestCaseData> 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);
}
}
}
}

@ -71,6 +71,7 @@
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="DateTimeHelperTests.cs" />
<Compile Include="PasswordHasherTests.cs" />
<Compile Include="HtmlRemoverTests.cs" />
<Compile Include="AssemblyHelperTests.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<IEnumerable<ScheduledJobs>> GetJobsAsync();
IEnumerable<ScheduledJobs> GetJobs();
}
}

@ -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<ScheduledJobs> Repo { get; }
public void Record(string jobName)
{
var allJobs = Repo.GetAll();
@ -55,5 +59,15 @@ namespace PlexRequests.Services
Repo.Insert(job);
}
}
public async Task<IEnumerable<ScheduledJobs>> GetJobsAsync()
{
return await Repo.GetAllAsync();
}
public IEnumerable<ScheduledJobs> GetJobs()
{
return Repo.GetAll();
}
}
}

@ -60,6 +60,7 @@ namespace PlexRequests.UI.Tests
private Mock<ISettingsService<PlexSettings>> PlexSettingsMock { get; set; }
private Mock<ISettingsService<SonarrSettings>> SonarrSettingsMock { get; set; }
private Mock<ISettingsService<SickRageSettings>> SickRageSettingsMock { get; set; }
private Mock<ISettingsService<ScheduledJobsSettings>> ScheduledJobsSettingsMock { get; set; }
private Mock<ISettingsService<EmailNotificationSettings>> EmailMock { get; set; }
private Mock<ISettingsService<PushbulletNotificationSettings>> PushbulletSettings { get; set; }
private Mock<ISettingsService<PushoverNotificationSettings>> PushoverSettings { get; set; }
@ -69,6 +70,7 @@ namespace PlexRequests.UI.Tests
private Mock<IPushbulletApi> PushbulletApi { get; set; }
private Mock<IPushoverApi> PushoverApi { get; set; }
private Mock<ICouchPotatoApi> CpApi { get; set; }
private Mock<IJobRecord> RecorderMock { get; set; }
private Mock<IRepository<LogEntity>> LogRepo { get; set; }
private Mock<INotificationService> NotificationService { get; set; }
private Mock<ICacheProvider> Cache { get; set; }
@ -111,6 +113,8 @@ namespace PlexRequests.UI.Tests
SlackApi = new Mock<ISlackApi>();
SlackSettings = new Mock<ISettingsService<SlackNotificationSettings>>();
LandingPageSettings = new Mock<ISettingsService<LandingPageSettings>>();
ScheduledJobsSettingsMock = new Mock<ISettingsService<ScheduledJobsSettings>>();
RecorderMock = new Mock<IJobRecord>();
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<TestRootPathProvider>();
with.RequestStartup((container, pipelines, context) =>
{

@ -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<TestCaseData> NoticeEnabledData

@ -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<ISettingsService<PushbulletNotificationSettings>, SettingsServiceV2<PushbulletNotificationSettings>>();
container.Register<ISettingsService<PushoverNotificationSettings>, SettingsServiceV2<PushoverNotificationSettings>>();
container.Register<ISettingsService<SlackNotificationSettings>, SettingsServiceV2<SlackNotificationSettings>>();
container.Register<ISettingsService<ScheduledJobsSettings>, SettingsServiceV2<ScheduledJobsSettings>>();
// Notification Service
container.Register<INotificationService, NotificationService>().AsSingleton();
@ -203,6 +206,9 @@ namespace PlexRequests.UI
container.Register<IJobFactory, CustomJobFactory>();
container.Register<IAnalytics, Analytics>();
container.Register<ISchedulerFactory, StdSchedulerFactory>();
container.Register<IJobScheduler, Scheduler>();
// Api
container.Register<ICouchPotatoApi, CouchPotatoApi>();

@ -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({

@ -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<ITrigger> CreateTriggers()
{
var settingsService = Service.Resolve<ISettingsService<ScheduledJobsSettings>>();
var s = settingsService.GetSettings();
var triggers = new List<ITrigger>();
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();
}
}

@ -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<string,DateTime> JobRecorder { get; set; }
}
}

@ -86,7 +86,9 @@ namespace PlexRequests.UI.Modules
private ICacheProvider Cache { get; }
private ISettingsService<SlackNotificationSettings> SlackSettings { get; }
private ISettingsService<LandingPageSettings> LandingSettings { get; }
private ISettingsService<ScheduledJobsSettings> ScheduledJobSettings { get; }
private ISlackApi SlackApi { get; }
private IJobRecord JobRecorder { get; }
private static Logger Log = LogManager.GetCurrentClassLogger();
public AdminModule(ISettingsService<PlexRequestSettings> prService,
@ -108,7 +110,8 @@ namespace PlexRequests.UI.Modules
ISettingsService<HeadphonesSettings> headphones,
ISettingsService<LogSettings> logs,
ICacheProvider cache, ISettingsService<SlackNotificationSettings> slackSettings,
ISlackApi slackApi, ISettingsService<LandingPageSettings> lp) : base("admin", prService)
ISlackApi slackApi, ISettingsService<LandingPageSettings> lp,
ISettingsService<ScheduledJobsSettings> 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<Negotiator> 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<Negotiator> 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<Response> SaveScheduledJobs()
{
var settings = this.Bind<ScheduledJobsSettings>();
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" });
}
}
}

@ -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<PlexRequestSettings> 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;

@ -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);
}
}
}
}

@ -182,6 +182,7 @@
<Compile Include="Models\LandingPageViewModel.cs" />
<Compile Include="Models\MovieSearchType.cs" />
<Compile Include="Models\QualityModel.cs" />
<Compile Include="Models\ScheduledJobsViewModel.cs" />
<Compile Include="Models\SearchViewModel.cs" />
<Compile Include="Models\SearchMusicViewModel.cs" />
<Compile Include="Models\SearchMovieViewModel.cs" />
@ -557,6 +558,9 @@
<Content Include="Views\Shared\Blank.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Views\Admin\SchedulerSettings.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<None Include="Web.Debug.config">
<DependentUpon>web.config</DependentUpon>
</None>

@ -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();
}

@ -0,0 +1,109 @@
@using PlexRequests.UI.Helpers
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<PlexRequests.UI.Models.ScheduledJobsViewModel>
@Html.Partial("_Sidebar")
<div class="col-sm-8 col-sm-push-1">
<div class="row">
<div class="col-md-3"><strong>Job Name</strong></div>
<div class="col-md-8"><strong>Last Run</strong></div>
</div>
@foreach (var record in Model.JobRecorder)
{
<div class="row">
<div class="col-md-3">@record.Key</div>
<div class="col-md-8 date">@record.Value.ToString("O")</div>
</div>
}
<br/>
<br/>
<form class="form-horizontal" method="POST" id="mainForm">
<fieldset>
<legend>Scheduler Settings</legend>
<small>Please note, you will need to restart for these settings to take effect</small>
<div class="form-group">
<label for="PlexAvailabilityChecker" class="control-label">Plex Availability Checker (min)</label>
<input type="text" class="form-control form-control-custom " id="PlexAvailabilityChecker" name="PlexAvailabilityChecker" value="@Model.PlexAvailabilityChecker">
</div>
<div class="form-group">
<label for="CouchPotatoCacher" class="control-label">Couch Potato Cacher (min)</label>
<input type="text" class="form-control form-control-custom " id="CouchPotatoCacher" name="CouchPotatoCacher" value="@Model.CouchPotatoCacher">
</div>
<div class="form-group">
<label for="SonarrCacher" class="control-label">Sonarr Cacher (min)</label>
<div>
<input type="text" class="form-control form-control-custom " id="SonarrCacher" name="SonarrCacher" value="@Model.SonarrCacher">
</div>
</div>
<div class="form-group">
<label for="SickRageCacher" class="control-label">SickRage Cacher (min)</label>
<div>
<input type="text" class="form-control form-control-custom " id="SickRageCacher" name="SickRageCacher" value="@Model.SickRageCacher">
</div>
</div>
<div class="form-group">
<label for="StoreBackup" class="control-label">Store Backup (hour)</label>
<div>
<input type="text" class="form-control form-control-custom " id="StoreBackup" name="StoreBackup" value="@Model.StoreBackup">
</div>
</div>
<div class="form-group">
<label for="StoreCleanup" class="control-label">Store Cleanup (hour)</label>
<div>
<input type="text" class="form-control form-control-custom " id="StoreCleanup" name="StoreCleanup" value="@Model.StoreCleanup">
</div>
</div>
<div class="form-group">
<div>
<button id="save" type="submit" class="btn btn-primary-outline ">Submit</button>
</div>
</div>
</fieldset>
</form>
</div>
<script>
$(function () {
$('.date').each(function (i, obj) {
var $obj = $(obj);
var val = $obj.text();
var newDate = utcToLocal(val);
$obj.text(newDate);
});
$('#save')
.click(function (e) {
e.preventDefault();
var $form = $("#mainForm");
var data = $form.serialize();
$.ajax({
type: $form.prop("method"),
data: data,
url: $form.prop("action"),
dataType: "json",
success: function (response) {
if (response.result === true) {
generateNotify("Success!", "success");
} else {
generateNotify(response.message, "warning");
}
},
error: function (e) {
console.log(e);
generateNotify("Something went wrong!", "danger");
}
});
});
});
</script>
Loading…
Cancel
Save