mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-10 15:32:37 -07:00
done #318
This commit is contained in:
parent
e8706354b9
commit
3e16d8acf0
18 changed files with 399 additions and 57 deletions
|
@ -78,6 +78,7 @@
|
||||||
<Compile Include="SettingModels\AuthenticationSettings.cs" />
|
<Compile Include="SettingModels\AuthenticationSettings.cs" />
|
||||||
<Compile Include="SettingModels\HeadphonesSettings.cs" />
|
<Compile Include="SettingModels\HeadphonesSettings.cs" />
|
||||||
<Compile Include="SettingModels\LandingPageSettings.cs" />
|
<Compile Include="SettingModels\LandingPageSettings.cs" />
|
||||||
|
<Compile Include="SettingModels\ScheduledJobsSettings.cs" />
|
||||||
<Compile Include="SettingModels\SlackNotificationSettings.cs" />
|
<Compile Include="SettingModels\SlackNotificationSettings.cs" />
|
||||||
<Compile Include="SettingModels\PushoverNotificationSettings.cs" />
|
<Compile Include="SettingModels\PushoverNotificationSettings.cs" />
|
||||||
<Compile Include="SettingModels\PushBulletNotificationSettings.cs" />
|
<Compile Include="SettingModels\PushBulletNotificationSettings.cs" />
|
||||||
|
|
47
PlexRequests.Core/SettingModels/ScheduledJobsSettings.cs
Normal file
47
PlexRequests.Core/SettingModels/ScheduledJobsSettings.cs
Normal file
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
54
PlexRequests.Helpers.Tests/DateTimeHelperTests.cs
Normal file
54
PlexRequests.Helpers.Tests/DateTimeHelperTests.cs
Normal file
|
@ -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>
|
</Otherwise>
|
||||||
</Choose>
|
</Choose>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="DateTimeHelperTests.cs" />
|
||||||
<Compile Include="PasswordHasherTests.cs" />
|
<Compile Include="PasswordHasherTests.cs" />
|
||||||
<Compile Include="HtmlRemoverTests.cs" />
|
<Compile Include="HtmlRemoverTests.cs" />
|
||||||
<Compile Include="AssemblyHelperTests.cs" />
|
<Compile Include="AssemblyHelperTests.cs" />
|
||||||
|
|
|
@ -24,10 +24,17 @@
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
#endregion
|
#endregion
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using PlexRequests.Store.Models;
|
||||||
|
|
||||||
namespace PlexRequests.Services.Interfaces
|
namespace PlexRequests.Services.Interfaces
|
||||||
{
|
{
|
||||||
public interface IJobRecord
|
public interface IJobRecord
|
||||||
{
|
{
|
||||||
void Record(string jobName);
|
void Record(string jobName);
|
||||||
|
Task<IEnumerable<ScheduledJobs>> GetJobsAsync();
|
||||||
|
IEnumerable<ScheduledJobs> GetJobs();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -25,13 +25,15 @@
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
#endregion
|
#endregion
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using PlexRequests.Services.Interfaces;
|
using PlexRequests.Services.Interfaces;
|
||||||
using PlexRequests.Store.Models;
|
using PlexRequests.Store.Models;
|
||||||
using PlexRequests.Store.Repository;
|
using PlexRequests.Store.Repository;
|
||||||
|
|
||||||
namespace PlexRequests.Services
|
namespace PlexRequests.Services.Jobs
|
||||||
{
|
{
|
||||||
public class JobRecord : IJobRecord
|
public class JobRecord : IJobRecord
|
||||||
{
|
{
|
||||||
|
@ -39,7 +41,9 @@ namespace PlexRequests.Services
|
||||||
{
|
{
|
||||||
Repo = repo;
|
Repo = repo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IRepository<ScheduledJobs> Repo { get; }
|
private IRepository<ScheduledJobs> Repo { get; }
|
||||||
|
|
||||||
public void Record(string jobName)
|
public void Record(string jobName)
|
||||||
{
|
{
|
||||||
var allJobs = Repo.GetAll();
|
var allJobs = Repo.GetAll();
|
||||||
|
@ -55,5 +59,15 @@ namespace PlexRequests.Services
|
||||||
Repo.Insert(job);
|
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<PlexSettings>> PlexSettingsMock { get; set; }
|
||||||
private Mock<ISettingsService<SonarrSettings>> SonarrSettingsMock { get; set; }
|
private Mock<ISettingsService<SonarrSettings>> SonarrSettingsMock { get; set; }
|
||||||
private Mock<ISettingsService<SickRageSettings>> SickRageSettingsMock { 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<EmailNotificationSettings>> EmailMock { get; set; }
|
||||||
private Mock<ISettingsService<PushbulletNotificationSettings>> PushbulletSettings { get; set; }
|
private Mock<ISettingsService<PushbulletNotificationSettings>> PushbulletSettings { get; set; }
|
||||||
private Mock<ISettingsService<PushoverNotificationSettings>> PushoverSettings { 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<IPushbulletApi> PushbulletApi { get; set; }
|
||||||
private Mock<IPushoverApi> PushoverApi { get; set; }
|
private Mock<IPushoverApi> PushoverApi { get; set; }
|
||||||
private Mock<ICouchPotatoApi> CpApi { get; set; }
|
private Mock<ICouchPotatoApi> CpApi { get; set; }
|
||||||
|
private Mock<IJobRecord> RecorderMock { get; set; }
|
||||||
private Mock<IRepository<LogEntity>> LogRepo { get; set; }
|
private Mock<IRepository<LogEntity>> LogRepo { get; set; }
|
||||||
private Mock<INotificationService> NotificationService { get; set; }
|
private Mock<INotificationService> NotificationService { get; set; }
|
||||||
private Mock<ICacheProvider> Cache { get; set; }
|
private Mock<ICacheProvider> Cache { get; set; }
|
||||||
|
@ -111,6 +113,8 @@ namespace PlexRequests.UI.Tests
|
||||||
SlackApi = new Mock<ISlackApi>();
|
SlackApi = new Mock<ISlackApi>();
|
||||||
SlackSettings = new Mock<ISettingsService<SlackNotificationSettings>>();
|
SlackSettings = new Mock<ISettingsService<SlackNotificationSettings>>();
|
||||||
LandingPageSettings = new Mock<ISettingsService<LandingPageSettings>>();
|
LandingPageSettings = new Mock<ISettingsService<LandingPageSettings>>();
|
||||||
|
ScheduledJobsSettingsMock = new Mock<ISettingsService<ScheduledJobsSettings>>();
|
||||||
|
RecorderMock = new Mock<IJobRecord>();
|
||||||
|
|
||||||
|
|
||||||
Bootstrapper = new ConfigurableBootstrapper(with =>
|
Bootstrapper = new ConfigurableBootstrapper(with =>
|
||||||
|
@ -138,6 +142,8 @@ namespace PlexRequests.UI.Tests
|
||||||
with.Dependency(SlackApi.Object);
|
with.Dependency(SlackApi.Object);
|
||||||
with.Dependency(LandingPageSettings.Object);
|
with.Dependency(LandingPageSettings.Object);
|
||||||
with.Dependency(SlackSettings.Object);
|
with.Dependency(SlackSettings.Object);
|
||||||
|
with.Dependency(ScheduledJobsSettingsMock.Object);
|
||||||
|
with.Dependency(RecorderMock.Object);
|
||||||
with.RootPathProvider<TestRootPathProvider>();
|
with.RootPathProvider<TestRootPathProvider>();
|
||||||
with.RequestStartup((container, pipelines, context) =>
|
with.RequestStartup((container, pipelines, context) =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace PlexRequests.UI.Tests
|
||||||
[TestCaseSource(nameof(NoticeEnabledData))]
|
[TestCaseSource(nameof(NoticeEnabledData))]
|
||||||
public bool TestNoticeEnabled(DateTime start, DateTime end)
|
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
|
private static IEnumerable<TestCaseData> NoticeEnabledData
|
||||||
|
|
|
@ -56,6 +56,8 @@ using PlexRequests.Helpers.Analytics;
|
||||||
using PlexRequests.Services.Jobs;
|
using PlexRequests.Services.Jobs;
|
||||||
using PlexRequests.UI.Jobs;
|
using PlexRequests.UI.Jobs;
|
||||||
|
|
||||||
|
using Quartz;
|
||||||
|
using Quartz.Impl;
|
||||||
using Quartz.Spi;
|
using Quartz.Spi;
|
||||||
|
|
||||||
namespace PlexRequests.UI
|
namespace PlexRequests.UI
|
||||||
|
@ -170,6 +172,7 @@ namespace PlexRequests.UI
|
||||||
container.Register<ISettingsService<PushbulletNotificationSettings>, SettingsServiceV2<PushbulletNotificationSettings>>();
|
container.Register<ISettingsService<PushbulletNotificationSettings>, SettingsServiceV2<PushbulletNotificationSettings>>();
|
||||||
container.Register<ISettingsService<PushoverNotificationSettings>, SettingsServiceV2<PushoverNotificationSettings>>();
|
container.Register<ISettingsService<PushoverNotificationSettings>, SettingsServiceV2<PushoverNotificationSettings>>();
|
||||||
container.Register<ISettingsService<SlackNotificationSettings>, SettingsServiceV2<SlackNotificationSettings>>();
|
container.Register<ISettingsService<SlackNotificationSettings>, SettingsServiceV2<SlackNotificationSettings>>();
|
||||||
|
container.Register<ISettingsService<ScheduledJobsSettings>, SettingsServiceV2<ScheduledJobsSettings>>();
|
||||||
|
|
||||||
// Notification Service
|
// Notification Service
|
||||||
container.Register<INotificationService, NotificationService>().AsSingleton();
|
container.Register<INotificationService, NotificationService>().AsSingleton();
|
||||||
|
@ -203,6 +206,9 @@ namespace PlexRequests.UI
|
||||||
container.Register<IJobFactory, CustomJobFactory>();
|
container.Register<IJobFactory, CustomJobFactory>();
|
||||||
|
|
||||||
container.Register<IAnalytics, Analytics>();
|
container.Register<IAnalytics, Analytics>();
|
||||||
|
container.Register<ISchedulerFactory, StdSchedulerFactory>();
|
||||||
|
container.Register<IJobScheduler, Scheduler>();
|
||||||
|
|
||||||
|
|
||||||
// Api
|
// Api
|
||||||
container.Register<ICouchPotatoApi, CouchPotatoApi>();
|
container.Register<ICouchPotatoApi, CouchPotatoApi>();
|
||||||
|
|
|
@ -14,6 +14,10 @@ function Humanize(date) {
|
||||||
return moment.duration(mNow - mDate).humanize() + (mNow.isBefore(mDate) ? ' from now' : ' ago');
|
return moment.duration(mNow - mDate).humanize() + (mNow.isBefore(mDate) ? ' from now' : ' ago');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function utcToLocal(date) {
|
||||||
|
return moment(date).local();
|
||||||
|
}
|
||||||
|
|
||||||
function generateNotify(message, type) {
|
function generateNotify(message, type) {
|
||||||
// type = danger, warning, info, successs
|
// type = danger, warning, info, successs
|
||||||
$.notify({
|
$.notify({
|
||||||
|
|
|
@ -30,16 +30,20 @@ using System.Linq;
|
||||||
|
|
||||||
using NLog;
|
using NLog;
|
||||||
|
|
||||||
|
using PlexRequests.Core;
|
||||||
|
using PlexRequests.Core.SettingModels;
|
||||||
using PlexRequests.Services.Jobs;
|
using PlexRequests.Services.Jobs;
|
||||||
|
using PlexRequests.UI.Helpers;
|
||||||
|
|
||||||
using Quartz;
|
using Quartz;
|
||||||
using Quartz.Impl;
|
using Quartz.Impl;
|
||||||
|
|
||||||
namespace PlexRequests.UI.Jobs
|
namespace PlexRequests.UI.Jobs
|
||||||
{
|
{
|
||||||
internal sealed class Scheduler
|
internal sealed class Scheduler : IJobScheduler
|
||||||
{
|
{
|
||||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
private IServiceLocator Service => ServiceLocator.Instance;
|
||||||
|
|
||||||
private readonly ISchedulerFactory _factory;
|
private readonly ISchedulerFactory _factory;
|
||||||
|
|
||||||
|
@ -99,48 +103,51 @@ namespace PlexRequests.UI.Jobs
|
||||||
|
|
||||||
private IEnumerable<ITrigger> CreateTriggers()
|
private IEnumerable<ITrigger> CreateTriggers()
|
||||||
{
|
{
|
||||||
|
var settingsService = Service.Resolve<ISettingsService<ScheduledJobsSettings>>();
|
||||||
|
var s = settingsService.GetSettings();
|
||||||
|
|
||||||
var triggers = new List<ITrigger>();
|
var triggers = new List<ITrigger>();
|
||||||
|
|
||||||
var plexAvailabilityChecker =
|
var plexAvailabilityChecker =
|
||||||
TriggerBuilder.Create()
|
TriggerBuilder.Create()
|
||||||
.WithIdentity("PlexAvailabilityChecker", "Plex")
|
.WithIdentity("PlexAvailabilityChecker", "Plex")
|
||||||
.StartNow()
|
.StartNow()
|
||||||
.WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever())
|
.WithSimpleSchedule(x => x.WithIntervalInMinutes(s.PlexAvailabilityChecker).RepeatForever())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var srCacher =
|
var srCacher =
|
||||||
TriggerBuilder.Create()
|
TriggerBuilder.Create()
|
||||||
.WithIdentity("SickRageCacher", "Cache")
|
.WithIdentity("SickRageCacher", "Cache")
|
||||||
.StartNow()
|
.StartNow()
|
||||||
.WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever())
|
.WithSimpleSchedule(x => x.WithIntervalInMinutes(s.SickRageCacher).RepeatForever())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var sonarrCacher =
|
var sonarrCacher =
|
||||||
TriggerBuilder.Create()
|
TriggerBuilder.Create()
|
||||||
.WithIdentity("SonarrCacher", "Cache")
|
.WithIdentity("SonarrCacher", "Cache")
|
||||||
.StartNow()
|
.StartNow()
|
||||||
.WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever())
|
.WithSimpleSchedule(x => x.WithIntervalInMinutes(s.SonarrCacher).RepeatForever())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var cpCacher =
|
var cpCacher =
|
||||||
TriggerBuilder.Create()
|
TriggerBuilder.Create()
|
||||||
.WithIdentity("CouchPotatoCacher", "Cache")
|
.WithIdentity("CouchPotatoCacher", "Cache")
|
||||||
.StartNow()
|
.StartNow()
|
||||||
.WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever())
|
.WithSimpleSchedule(x => x.WithIntervalInMinutes(s.CouchPotatoCacher).RepeatForever())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var storeBackup =
|
var storeBackup =
|
||||||
TriggerBuilder.Create()
|
TriggerBuilder.Create()
|
||||||
.WithIdentity("StoreBackup", "Database")
|
.WithIdentity("StoreBackup", "Database")
|
||||||
.StartNow()
|
.StartNow()
|
||||||
.WithSimpleSchedule(x => x.WithIntervalInHours(24).RepeatForever())
|
.WithSimpleSchedule(x => x.WithIntervalInHours(s.StoreBackup).RepeatForever())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var storeCleanup =
|
var storeCleanup =
|
||||||
TriggerBuilder.Create()
|
TriggerBuilder.Create()
|
||||||
.WithIdentity("StoreCleanup", "Database")
|
.WithIdentity("StoreCleanup", "Database")
|
||||||
.StartNow()
|
.StartNow()
|
||||||
.WithSimpleSchedule(x => x.WithIntervalInHours(24).RepeatForever())
|
.WithSimpleSchedule(x => x.WithIntervalInHours(s.StoreCleanup).RepeatForever())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,4 +161,9 @@ namespace PlexRequests.UI.Jobs
|
||||||
return triggers;
|
return triggers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IJobScheduler
|
||||||
|
{
|
||||||
|
void StartScheduler();
|
||||||
|
}
|
||||||
}
|
}
|
38
PlexRequests.UI/Models/ScheduledJobsViewModel.cs
Normal file
38
PlexRequests.UI/Models/ScheduledJobsViewModel.cs
Normal file
|
@ -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 ICacheProvider Cache { get; }
|
||||||
private ISettingsService<SlackNotificationSettings> SlackSettings { get; }
|
private ISettingsService<SlackNotificationSettings> SlackSettings { get; }
|
||||||
private ISettingsService<LandingPageSettings> LandingSettings { get; }
|
private ISettingsService<LandingPageSettings> LandingSettings { get; }
|
||||||
|
private ISettingsService<ScheduledJobsSettings> ScheduledJobSettings { get; }
|
||||||
private ISlackApi SlackApi { get; }
|
private ISlackApi SlackApi { get; }
|
||||||
|
private IJobRecord JobRecorder { get; }
|
||||||
|
|
||||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
public AdminModule(ISettingsService<PlexRequestSettings> prService,
|
public AdminModule(ISettingsService<PlexRequestSettings> prService,
|
||||||
|
@ -108,7 +110,8 @@ namespace PlexRequests.UI.Modules
|
||||||
ISettingsService<HeadphonesSettings> headphones,
|
ISettingsService<HeadphonesSettings> headphones,
|
||||||
ISettingsService<LogSettings> logs,
|
ISettingsService<LogSettings> logs,
|
||||||
ICacheProvider cache, ISettingsService<SlackNotificationSettings> slackSettings,
|
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;
|
PrService = prService;
|
||||||
CpService = cpService;
|
CpService = cpService;
|
||||||
|
@ -132,6 +135,8 @@ namespace PlexRequests.UI.Modules
|
||||||
SlackSettings = slackSettings;
|
SlackSettings = slackSettings;
|
||||||
SlackApi = slackApi;
|
SlackApi = slackApi;
|
||||||
LandingSettings = lp;
|
LandingSettings = lp;
|
||||||
|
ScheduledJobSettings = scheduler;
|
||||||
|
JobRecorder = rec;
|
||||||
|
|
||||||
this.RequiresClaims(UserClaims.Admin);
|
this.RequiresClaims(UserClaims.Admin);
|
||||||
|
|
||||||
|
@ -193,6 +198,9 @@ namespace PlexRequests.UI.Modules
|
||||||
|
|
||||||
Get["/landingpage", true] = async (x, ct) => await LandingPage();
|
Get["/landingpage", true] = async (x, ct) => await LandingPage();
|
||||||
Post["/landingpage", true] = async (x, ct) => await SaveLandingPage();
|
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()
|
private async Task<Negotiator> Authentication()
|
||||||
|
@ -835,5 +843,34 @@ namespace PlexRequests.UI.Modules
|
||||||
? new JsonResponseModel { Result = true }
|
? new JsonResponseModel { Result = true }
|
||||||
: new JsonResponseModel { Result = false, Message = "Could not save to Db Please check the logs" });
|
: 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
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using Nancy;
|
using Nancy;
|
||||||
using Nancy.Extensions;
|
using Nancy.Extensions;
|
||||||
using PlexRequests.UI.Models;
|
using PlexRequests.UI.Models;
|
||||||
using System;
|
|
||||||
|
|
||||||
using PlexRequests.Core;
|
using PlexRequests.Core;
|
||||||
using PlexRequests.Core.SettingModels;
|
using PlexRequests.Core.SettingModels;
|
||||||
using PlexRequests.Helpers;
|
|
||||||
|
|
||||||
namespace PlexRequests.UI.Modules
|
namespace PlexRequests.UI.Modules
|
||||||
{
|
{
|
||||||
public abstract class BaseAuthModule : BaseModule
|
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)
|
protected BaseAuthModule(ISettingsService<PlexRequestSettings> pr) : base(pr)
|
||||||
{
|
{
|
||||||
PlexRequestSettings = pr;
|
PlexRequestSettings = pr;
|
||||||
|
@ -101,7 +56,7 @@ namespace PlexRequests.UI.Modules
|
||||||
var baseUrl = settings.BaseUrl;
|
var baseUrl = settings.BaseUrl;
|
||||||
|
|
||||||
var redirectPath = string.IsNullOrEmpty(baseUrl) ? "~/userlogin" : $"~/{baseUrl}/userlogin";
|
var redirectPath = string.IsNullOrEmpty(baseUrl) ? "~/userlogin" : $"~/{baseUrl}/userlogin";
|
||||||
|
|
||||||
return Session[SessionKeys.UsernameKey] == null
|
return Session[SessionKeys.UsernameKey] == null
|
||||||
? Context.GetRedirect(redirectPath)
|
? Context.GetRedirect(redirectPath)
|
||||||
: null;
|
: null;
|
||||||
|
|
|
@ -24,10 +24,15 @@
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
#endregion
|
#endregion
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
using Nancy;
|
using Nancy;
|
||||||
|
|
||||||
using PlexRequests.Core;
|
using PlexRequests.Core;
|
||||||
using PlexRequests.Core.SettingModels;
|
using PlexRequests.Core.SettingModels;
|
||||||
|
using PlexRequests.Helpers;
|
||||||
|
using PlexRequests.UI.Models;
|
||||||
|
|
||||||
namespace PlexRequests.UI.Modules
|
namespace PlexRequests.UI.Modules
|
||||||
{
|
{
|
||||||
|
@ -56,5 +61,45 @@ namespace PlexRequests.UI.Modules
|
||||||
|
|
||||||
ModulePath = settingModulePath;
|
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\LandingPageViewModel.cs" />
|
||||||
<Compile Include="Models\MovieSearchType.cs" />
|
<Compile Include="Models\MovieSearchType.cs" />
|
||||||
<Compile Include="Models\QualityModel.cs" />
|
<Compile Include="Models\QualityModel.cs" />
|
||||||
|
<Compile Include="Models\ScheduledJobsViewModel.cs" />
|
||||||
<Compile Include="Models\SearchViewModel.cs" />
|
<Compile Include="Models\SearchViewModel.cs" />
|
||||||
<Compile Include="Models\SearchMusicViewModel.cs" />
|
<Compile Include="Models\SearchMusicViewModel.cs" />
|
||||||
<Compile Include="Models\SearchMovieViewModel.cs" />
|
<Compile Include="Models\SearchMovieViewModel.cs" />
|
||||||
|
@ -557,6 +558,9 @@
|
||||||
<Content Include="Views\Shared\Blank.cshtml">
|
<Content Include="Views\Shared\Blank.cshtml">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Views\Admin\SchedulerSettings.cshtml">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<None Include="Web.Debug.config">
|
<None Include="Web.Debug.config">
|
||||||
<DependentUpon>web.config</DependentUpon>
|
<DependentUpon>web.config</DependentUpon>
|
||||||
</None>
|
</None>
|
||||||
|
|
|
@ -26,10 +26,13 @@
|
||||||
#endregion
|
#endregion
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
using Nancy.TinyIoc;
|
||||||
|
|
||||||
using NLog;
|
using NLog;
|
||||||
|
|
||||||
using Owin;
|
using Owin;
|
||||||
|
|
||||||
|
using PlexRequests.UI.Helpers;
|
||||||
using PlexRequests.UI.Jobs;
|
using PlexRequests.UI.Jobs;
|
||||||
|
|
||||||
namespace PlexRequests.UI
|
namespace PlexRequests.UI
|
||||||
|
@ -43,7 +46,6 @@ namespace PlexRequests.UI
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
app.UseNancy();
|
app.UseNancy();
|
||||||
|
|
||||||
var scheduler = new Scheduler();
|
var scheduler = new Scheduler();
|
||||||
scheduler.StartScheduler();
|
scheduler.StartScheduler();
|
||||||
}
|
}
|
||||||
|
|
109
PlexRequests.UI/Views/Admin/SchedulerSettings.cshtml
Normal file
109
PlexRequests.UI/Views/Admin/SchedulerSettings.cshtml
Normal file
|
@ -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…
Add table
Add a link
Reference in a new issue