(`${this.url}/sickrage`, {headers: this.headers});
diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html
index ff5e56ed8..02eb51d77 100644
--- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html
+++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html
@@ -12,29 +12,34 @@
The Sonarr Sync is required
+
The SickRage Sync is required
+
The Radarr Sync is required
+
The CouchPotato Sync is required
+
The Automatic Update is required
+
@@ -50,21 +55,37 @@
The Plex Sync is required
+
The Emby Sync is required
+
The User Importer is required
+
+
+
+
+
+
+ The Refresh Metadata is required
+
-
\ No newline at end of file
+
+
+
+
+ - {{item | date:'short'}}
+
+
\ No newline at end of file
diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts
index f547c5056..380cef8de 100644
--- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts
+++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts
@@ -1,7 +1,10 @@
import { Component, OnInit } from "@angular/core";
+
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { NotificationService, SettingsService } from "../../services";
+import { ICronTestModel } from "./../../interfaces";
+
@Component({
templateUrl: "./jobs.component.html",
})
@@ -10,6 +13,8 @@ export class JobsComponent implements OnInit {
public form: FormGroup;
public profilesRunning: boolean;
+ public testModel: ICronTestModel;
+ public displayTest: boolean;
constructor(private readonly settingsService: SettingsService,
private readonly fb: FormBuilder,
@@ -26,7 +31,19 @@ export class JobsComponent implements OnInit {
sonarrSync: [x.radarrSync, Validators.required],
radarrSync: [x.sonarrSync, Validators.required],
sickRageSync: [x.sickRageSync, Validators.required],
- });
+ refreshMetadata: [x.refreshMetadata, Validators.required],
+ });
+ });
+ }
+
+ public testCron(expression: string) {
+ this.settingsService.testCron({ expression }).subscribe(x => {
+ if(x.success) {
+ this.testModel = x;
+ this.displayTest = true;
+ } else {
+ this.notificationService.error(x.message);
+ }
});
}
@@ -37,10 +54,10 @@ export class JobsComponent implements OnInit {
}
const settings = form.value;
this.settingsService.saveJobSettings(settings).subscribe(x => {
- if (x) {
+ if (x.result) {
this.notificationService.success("Successfully saved the job settings");
} else {
- this.notificationService.success("There was an error when saving the job settings");
+ this.notificationService.error("There was an error when saving the job settings. " + x.message);
}
});
}
diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts
index f10df8448..c95aa4362 100644
--- a/src/Ombi/ClientApp/app/settings/settings.module.ts
+++ b/src/Ombi/ClientApp/app/settings/settings.module.ts
@@ -41,7 +41,7 @@ import { WikiComponent } from "./wiki.component";
import { SettingsMenuComponent } from "./settingsmenu.component";
-import { AutoCompleteModule, CalendarModule, InputSwitchModule, InputTextModule, MenuModule, RadioButtonModule, TooltipModule } from "primeng/primeng";
+import { AutoCompleteModule, CalendarModule, DialogModule, InputSwitchModule, InputTextModule, MenuModule, RadioButtonModule, TooltipModule } from "primeng/primeng";
const routes: Routes = [
{ path: "Ombi", component: OmbiComponent, canActivate: [AuthGuard] },
@@ -88,6 +88,7 @@ const routes: Routes = [
ClipboardModule,
PipeModule,
RadioButtonModule,
+ DialogModule,
],
declarations: [
SettingsMenuComponent,
@@ -139,4 +140,4 @@ const routes: Routes = [
],
})
-export class SettingsModule { }
+export class SettingsModule { }
\ No newline at end of file
diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs
index c68a648c8..c0148c1bb 100644
--- a/src/Ombi/Controllers/SettingsController.cs
+++ b/src/Ombi/Controllers/SettingsController.cs
@@ -5,15 +5,18 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
+using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using Hangfire;
+using Hangfire.RecurringJobExtensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.PlatformAbstractions;
+using NCrontab;
using Ombi.Api.Emby;
using Ombi.Attributes;
using Ombi.Core.Models.UI;
@@ -465,7 +468,8 @@ namespace Ombi.Controllers
j.PlexContentSync = j.PlexContentSync.HasValue() ? j.PlexContentSync : JobSettingsHelper.PlexContent(j);
j.UserImporter = j.UserImporter.HasValue() ? j.UserImporter : JobSettingsHelper.UserImporter(j);
j.SickRageSync = j.SickRageSync.HasValue() ? j.SickRageSync : JobSettingsHelper.SickRageSync(j);
-
+ j.RefreshMetadata = j.RefreshMetadata.HasValue() ? j.RefreshMetadata : JobSettingsHelper.RefreshMetadata(j);
+
return j;
}
@@ -475,9 +479,71 @@ namespace Ombi.Controllers
/// The settings.
///
[HttpPost("jobs")]
- public async Task JobSettings([FromBody]JobSettings settings)
+ public async Task JobSettings([FromBody]JobSettings settings)
{
- return await Save(settings);
+ // Verify that we have correct CRON's
+ foreach (var propertyInfo in settings.GetType()
+ .GetProperties(BindingFlags.Public | BindingFlags.Instance))
+ {
+ if (propertyInfo.Name.Equals("Id", StringComparison.CurrentCultureIgnoreCase))
+ {
+ continue;
+ }
+ var expression = (string)propertyInfo.GetValue(settings, null);
+
+ try
+ {
+ var r = CrontabSchedule.TryParse(expression);
+ if (r == null)
+ {
+ return new JobSettingsViewModel
+ {
+ Message = $"{propertyInfo.Name} does not have a valid CRON Expression"
+ };
+ }
+ }
+ catch (Exception)
+ {
+ return new JobSettingsViewModel
+ {
+ Message = $"{propertyInfo.Name} does not have a valid CRON Expression"
+ };
+ }
+ }
+ var result = await Save(settings);
+
+ return new JobSettingsViewModel
+ {
+ Result = result
+ };
+ }
+
+ [HttpPost("testcron")]
+ public CronTestModel TestCron([FromBody] CronViewModelBody body)
+ {
+ var model = new CronTestModel();
+ try
+ {
+ var time = DateTime.UtcNow;
+ var result = CrontabSchedule.TryParse(body.Expression);
+ for (int i = 0; i < 10; i++)
+ {
+ var next = result.GetNextOccurrence(time);
+ model.Schedule.Add(next);
+ time = next;
+ }
+ model.Success = true;
+ return model;
+ }
+ catch (Exception)
+ {
+ return new CronTestModel
+ {
+ Message = $"CRON Expression {body.Expression} is not valid"
+ };
+ }
+
+
}
diff --git a/src/Ombi/Models/CronTestModel.cs b/src/Ombi/Models/CronTestModel.cs
new file mode 100644
index 000000000..9698afbff
--- /dev/null
+++ b/src/Ombi/Models/CronTestModel.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+
+namespace Ombi.Models
+{
+ public class CronTestModel
+ {
+ public bool Success { get; set; }
+ public string Message { get; set; }
+ public List Schedule { get; set; } = new List();
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi/Models/CronViewModelBody.cs b/src/Ombi/Models/CronViewModelBody.cs
new file mode 100644
index 000000000..cd961eda1
--- /dev/null
+++ b/src/Ombi/Models/CronViewModelBody.cs
@@ -0,0 +1,7 @@
+namespace Ombi.Models
+{
+ public class CronViewModelBody
+ {
+ public string Expression { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi/Models/JobSettingsViewModel.cs b/src/Ombi/Models/JobSettingsViewModel.cs
new file mode 100644
index 000000000..75006b86a
--- /dev/null
+++ b/src/Ombi/Models/JobSettingsViewModel.cs
@@ -0,0 +1,8 @@
+namespace Ombi.Models
+{
+ public class JobSettingsViewModel
+ {
+ public bool Result { get; set; }
+ public string Message { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj
index 6ab7770e6..393de0e23 100644
--- a/src/Ombi/Ombi.csproj
+++ b/src/Ombi/Ombi.csproj
@@ -65,11 +65,12 @@
-
-
-
-
+
+
+
+
+
diff --git a/src/Ombi/Ombi.testdb b/src/Ombi/Ombi.testdb
deleted file mode 100644
index c96d58f51..000000000
Binary files a/src/Ombi/Ombi.testdb and /dev/null differ