Lots of different UI enhancements and fixes #865

pull/1510/head
tidusjar 8 years ago
parent 855a11ba9a
commit ece8b39632

@ -19,6 +19,6 @@ namespace Ombi.Api.Sonarr
Task<bool> EpisodeSearch(int[] episodeIds, string apiKey, string baseUrl); Task<bool> EpisodeSearch(int[] episodeIds, string apiKey, string baseUrl);
Task<bool> SeasonSearch(int seriesId, int seasonNumber, string apiKey, string baseUrl); Task<bool> SeasonSearch(int seriesId, int seasonNumber, string apiKey, string baseUrl);
Task<bool> SeriesSearch(int seriesId, string apiKey, string baseUrl); Task<bool> SeriesSearch(int seriesId, string apiKey, string baseUrl);
Task<SystemStatus> SystemStatus(string apiKey, string baseUrl);
} }
} }

@ -0,0 +1,25 @@
namespace Ombi.Api.Sonarr
{
public class SystemStatus
{
public string version { get; set; }
public string buildTime { get; set; }
public bool isDebug { get; set; }
public bool isProduction { get; set; }
public bool isAdmin { get; set; }
public bool isUserInteractive { get; set; }
public string startupPath { get; set; }
public string appData { get; set; }
public string osVersion { get; set; }
public bool isMonoRuntime { get; set; }
public bool isMono { get; set; }
public bool isLinux { get; set; }
public bool isOsx { get; set; }
public bool isWindows { get; set; }
public string branch { get; set; }
public string authentication { get; set; }
public string sqliteVersion { get; set; }
public string urlBase { get; set; }
public string runtimeVersion { get; set; }
}
}

@ -188,5 +188,13 @@ namespace Ombi.Api.Sonarr
request.AddJsonBody(body); request.AddJsonBody(body);
return await Api.Request<CommandResult>(request); return await Api.Request<CommandResult>(request);
} }
public async Task<SystemStatus> SystemStatus(string apiKey, string baseUrl)
{
var request = new Request("/api/system/status", baseUrl, HttpMethod.Get);
request.AddHeader("X-Api-Key", apiKey);
return await Api.Request<SystemStatus>(request);
}
} }
} }

@ -149,8 +149,19 @@ namespace Ombi.Core.Engine
public async Task RemoveTvChild(int requestId) public async Task RemoveTvChild(int requestId)
{ {
var request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId); var request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId);
var all = TvRepository.Db.TvRequests.Include(x => x.ChildRequests);
var parent = all.FirstOrDefault(x => x.Id == request.ParentRequestId);
// Is this the only child? If so delete the parent
if (parent.ChildRequests.Count <= 1)
{
// Delete the parent
TvRepository.Db.TvRequests.Remove(parent);
}
await Audit.Record(AuditType.Deleted, AuditArea.TvRequest, $"Deleting Request {request.Title}", Username); await Audit.Record(AuditType.Deleted, AuditArea.TvRequest, $"Deleting Request {request.Title}", Username);
await TvRepository.DeleteChild(request);
TvRepository.Db.ChildRequests.Remove(request);
await TvRepository.Db.SaveChangesAsync();
} }
public async Task RemoveTvRequest(int requestId) public async Task RemoveTvRequest(int requestId)

@ -1,11 +1,13 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Store.Context;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
namespace Ombi.Store.Repository.Requests namespace Ombi.Store.Repository.Requests
{ {
public interface ITvRequestRepository public interface ITvRequestRepository
{ {
IOmbiContext Db { get; }
Task<TvRequests> Add(TvRequests request); Task<TvRequests> Add(TvRequests request);
Task<ChildRequests> AddChild(ChildRequests request); Task<ChildRequests> AddChild(ChildRequests request);
Task Delete(TvRequests request); Task Delete(TvRequests request);

@ -13,7 +13,7 @@ namespace Ombi.Store.Repository.Requests
Db = ctx; Db = ctx;
} }
private IOmbiContext Db { get; } public IOmbiContext Db { get; }
public async Task<TvRequests> GetRequestAsync(int tvDbId) public async Task<TvRequests> GetRequestAsync(int tvDbId)
{ {

@ -51,7 +51,7 @@ export class AuthService extends ServiceHelpers {
hasRole(role: string): boolean { hasRole(role: string): boolean {
return this.claims().roles.some(r => r === role); return this.claims().roles.some(r => r.toUpperCase() === role.toUpperCase());
} }
logout() { logout() {

@ -68,6 +68,7 @@
<span *ngIf="child.available" class="label label-success">Available</span> <span *ngIf="child.available" class="label label-success">Available</span>
<span *ngIf="child.denied" class="label label-danger">Denied</span> <span *ngIf="child.denied" class="label label-danger">Denied</span>
<span *ngIf="child.approved && !child.available && !child.denied" class="label label-info">Processing Request</span> <span *ngIf="child.approved && !child.available && !child.denied" class="label label-info">Processing Request</span>
<span *ngIf="!child.approved && !child.available" class="label label-info">Pending Approval</span>
</div> </div>
@ -95,7 +96,7 @@
<table class="table table-striped table-hover table-responsive table-condensed"> <table class="table table-striped table-hover table-responsive table-condensed">
<thead> <thead>
<tr> <tr>
<th> <th style="left">
<a>#</a> <a>#</a>
</th> </th>
<th> <th>
@ -125,7 +126,7 @@
<span *ngIf="ep.approved && !ep.available" class="label label-info">Processing Request</span> <span *ngIf="ep.approved && !ep.available" class="label label-info">Processing Request</span>
<div *ngIf="ep.requested && !ep.available; then requested else notRequested"></div> <div *ngIf="ep.requested && !ep.available; then requested else notRequested"></div>
<ng-template #requested> <ng-template #requested>
<span *ngIf="!ep.available" class="label label-warning">Pending Approval</span> <span *ngIf="!ep.available" class="label label-info">Pending Approval</span>
</ng-template> </ng-template>
<ng-template #notRequested> <ng-template #notRequested>

@ -12,3 +12,7 @@
.ui-treetable-toggler.fa.fa-fw.ui-c.fa-caret-down { .ui-treetable-toggler.fa.fa-fw.ui-c.fa-caret-down {
display: none; display: none;
} }
th {
text-align: left !important;
}

@ -11,7 +11,6 @@ import 'rxjs/add/operator/map';
import { RequestService } from '../services/request.service'; import { RequestService } from '../services/request.service';
import { AuthService } from '../auth/auth.service'; import { AuthService } from '../auth/auth.service';
import { IdentityService } from '../services/identity.service';
import { ITvRequests, IChildRequests, INewSeasonRequests, IEpisodesRequests } from '../interfaces/IRequestModel'; import { ITvRequests, IChildRequests, INewSeasonRequests, IEpisodesRequests } from '../interfaces/IRequestModel';
import { TreeNode, } from "primeng/primeng"; import { TreeNode, } from "primeng/primeng";
@ -27,7 +26,9 @@ import { TreeNode, } from "primeng/primeng";
}) })
export class TvRequestsComponent implements OnInit, OnDestroy { export class TvRequestsComponent implements OnInit, OnDestroy {
constructor(private requestService: RequestService, constructor(private requestService: RequestService,
private identityService: IdentityService, private authService : AuthService) { private authService: AuthService) {
this.admin = this.authService.hasRole("admin");
this.searchChanged this.searchChanged
.debounceTime(600) // Wait Xms afterthe last event before emitting last event .debounceTime(600) // Wait Xms afterthe last event before emitting last event
.distinctUntilChanged() // only emit if value is different from previous value .distinctUntilChanged() // only emit if value is different from previous value
@ -49,7 +50,6 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
this.currentlyLoaded = 5; this.currentlyLoaded = 5;
this.tvRequests = []; this.tvRequests = [];
this.loadInit(); this.loadInit();
this.admin = this.authService.hasRole("admin");
} }
public admin = false; public admin = false;
@ -157,14 +157,27 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
public approve(request: IChildRequests) { public approve(request: IChildRequests) {
request.approved = true; request.approved = true;
request.denied = false; request.denied = false;
// Mark all the episodes as approved now
request.seasonRequests.forEach((val) => {
val.episodes.forEach((ep) => {
ep.approved = true;
});
});
this.requestService.updateChild(request) this.requestService.updateChild(request)
.subscribe(); .subscribe();
} }
public deny(request: IChildRequests) { public deny(request: IChildRequests) {
debugger;
request.approved = false; request.approved = false;
request.denied = true; request.denied = true;
// Mark all the episodes as not approved now
request.seasonRequests.forEach((val) => {
val.episodes.forEach((ep) => {
ep.approved = false;
});
});
this.requestService.updateChild(request) this.requestService.updateChild(request)
.subscribe(); .subscribe();
} }
@ -214,10 +227,8 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
this.requestService.getTvRequests(this.amountToLoad, 0) this.requestService.getTvRequests(this.amountToLoad, 0)
.takeUntil(this.subscriptions) .takeUntil(this.subscriptions)
.subscribe(x => { .subscribe(x => {
debugger;
this.tvRequests = this.transformData(x); this.tvRequests = this.transformData(x);
}); });
this.isAdmin = this.identityService.hasRole("Admin");
} }
private resetSearch() { private resetSearch() {
@ -236,8 +247,13 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
var data = (<any>val).data; var data = (<any>val).data;
var index = data.childRequests.indexOf(key, 0); var index = data.childRequests.indexOf(key, 0);
if (index > -1) { if (index > -1) {
// Check if we need to remove the parent (if this is the only child)
if (data.childRequests.length <= 1) {
this.removeRequestFromUi(val);
} else {
data.childRequests.splice(index, 1); data.childRequests.splice(index, 1);
} }
}
}); });
} }

@ -65,6 +65,10 @@ export class SeriesInformationComponent implements OnInit, OnDestroy {
episode.requested = true; episode.requested = true;
} }
public removeRequest(episode: IEpisodesRequests) {
episode.requested = false;
}
ngOnDestroy(): void { ngOnDestroy(): void {
this.subscriptions.next(); this.subscriptions.next();

@ -13,6 +13,12 @@ import {
IMattermostNotifcationSettings IMattermostNotifcationSettings
} from '../../interfaces/INotifcationSettings' } from '../../interfaces/INotifcationSettings'
import {
IEmbyServer,
IPlexServer,
IRadarrSettings,
ISonarrSettings
} from '../../interfaces/ISettings';
@Injectable() @Injectable()
export class TesterService extends ServiceAuthHelpers { export class TesterService extends ServiceAuthHelpers {
@ -42,4 +48,16 @@ export class TesterService extends ServiceAuthHelpers {
emailTest(settings: IEmailNotificationSettings): Observable<boolean> { emailTest(settings: IEmailNotificationSettings): Observable<boolean> {
return this.http.post(`${this.url}email`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData); return this.http.post(`${this.url}email`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
} }
plexTest(settings: IPlexServer): Observable<boolean> {
return this.http.post(`${this.url}plex`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
}
embyTest(settings: IEmbyServer): Observable<boolean> {
return this.http.post(`${this.url}emby`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
}
radarrTest(settings: IRadarrSettings): Observable<boolean> {
return this.http.post(`${this.url}radarr`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
}
sonarrTest(settings: ISonarrSettings): Observable<boolean> {
return this.http.post(`${this.url}sonarr`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
}
} }

@ -3,14 +3,16 @@
import { IEmbySettings, IEmbyServer } from '../../interfaces/ISettings' import { IEmbySettings, IEmbyServer } from '../../interfaces/ISettings'
import { SettingsService } from '../../services/settings.service'; import { SettingsService } from '../../services/settings.service';
import { NotificationService } from "../../services/notification.service"; import { NotificationService } from "../../services/notification.service";
import { TesterService } from '../../services/applications/tester.service';
@Component({ @Component({
templateUrl: './emby.component.html'
templateUrl: './emby.component.html',
}) })
export class EmbyComponent implements OnInit { export class EmbyComponent implements OnInit {
constructor(private settingsService: SettingsService, private notificationService: NotificationService) { } constructor(private settingsService: SettingsService,
private notificationService: NotificationService,
private testerService : TesterService) { }
settings: IEmbySettings; settings: IEmbySettings;
@ -22,13 +24,37 @@ export class EmbyComponent implements OnInit {
if (this.settings.servers == null) { if (this.settings.servers == null) {
this.settings.servers = []; this.settings.servers = [];
} }
this.settings.servers.push(<IEmbyServer>{ name: "New*", id: Math.floor(Math.random() * (99999 - 0 + 1) + 1), apiKey: "", administratorId: "", enableEpisodeSearching: false, ip: "", port: 0, ssl: false, subDir: "" }); this.settings.servers.push({
name: "New*",
id: Math.floor(Math.random() * (99999 - 0 + 1) + 1),
apiKey: "",
administratorId: "",
enableEpisodeSearching: false,
ip: "",
port: 0,
ssl: false,
subDir: ""
} as IEmbyServer);
} }
test() { test(server: IEmbyServer) {
// TODO Emby Service this.testerService.embyTest(server).subscribe(x => {
if (x) {
this.notificationService.success("Connected", `Successfully connected to the Emby server ${server.name}!`);
} else {
this.notificationService.error("Connected", `We could not connect to the Emby server ${server.name}!`);
}
});
} }
removeServer(server: IEmbyServer) {
var index = this.settings.servers.indexOf(server, 0);
if (index > -1) {
this.settings.servers.splice(index, 1);
}
}
save() { save() {
this.settingsService.saveEmby(this.settings).subscribe(x => { this.settingsService.saveEmby(this.settings).subscribe(x => {
if (x) { if (x) {

@ -4,12 +4,12 @@
<legend>Ombi Configuration</legend> <legend>Ombi Configuration</legend>
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)"> <form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
<div class="form-group"> <!--<div class="form-group">
<label for="portNumber" class="control-label">Port</label> <label for="portNumber" class="control-label">Port</label>
<div> <div>
<input type="text" class="form-control form-control-custom " id="portNumber" name="Port" placeholder="Port Number" formControlName="port" pTooltip="You will have to restart after changing the port."> <input type="text" class="form-control form-control-custom " id="portNumber" name="Port" placeholder="Port Number" formControlName="port" pTooltip="You will have to restart after changing the port.">
</div> </div>
</div> </div>-->
<!--<div *ngIf="form.invalid && form.dirty" class="alert alert-danger"> <!--<div *ngIf="form.invalid && form.dirty" class="alert alert-danger">
<div>The External URL is incorrect</div> <div>The External URL is incorrect</div>

@ -30,9 +30,7 @@ export class OmbiComponent implements OnInit {
refreshApiKey() { refreshApiKey() {
this.settingsService.resetOmbiApi().subscribe(x => { this.settingsService.resetOmbiApi().subscribe(x => {
this.form.patchValue({ this.form.controls["apiKey"].patchValue(x);
apiKey: x
});
}); });
} }
@ -41,6 +39,8 @@ export class OmbiComponent implements OnInit {
this.notificationService.error("Validation", "Please check your entered values"); this.notificationService.error("Validation", "Please check your entered values");
return; return;
} }
this.settingsService.saveOmbi(form.value).subscribe(x => { this.settingsService.saveOmbi(form.value).subscribe(x => {
if (x) { if (x) {
this.notificationService.success("Settings Saved", "Successfully saved Ombi settings"); this.notificationService.success("Settings Saved", "Successfully saved Ombi settings");

@ -145,7 +145,7 @@
<div class="form-group"> <div class="form-group">
<div> <div>
<button id="testPlex" type="submit" (click)="testPlex()" class="btn btn-primary-outline"> <button id="testPlex" type="submit" (click)="testPlex(server)" class="btn btn-primary-outline">
Test Connectivity Test Connectivity
<div id="spinner"></div> <div id="spinner"></div>
</button> </button>

@ -6,6 +6,7 @@ import { IPlexSettings, IPlexLibraries, IPlexServer } from '../../interfaces/ISe
import { IPlexServerResponse, IPlexServerViewModel } from '../../interfaces/IPlex' import { IPlexServerResponse, IPlexServerViewModel } from '../../interfaces/IPlex'
import { SettingsService } from '../../services/settings.service'; import { SettingsService } from '../../services/settings.service';
import { TesterService } from '../../services/applications/tester.service';
import { PlexService } from '../../services/applications/plex.service'; import { PlexService } from '../../services/applications/plex.service';
import { NotificationService } from "../../services/notification.service"; import { NotificationService } from "../../services/notification.service";
@ -13,7 +14,10 @@ import { NotificationService } from "../../services/notification.service";
templateUrl: './plex.component.html', templateUrl: './plex.component.html',
}) })
export class PlexComponent implements OnInit, OnDestroy { export class PlexComponent implements OnInit, OnDestroy {
constructor(private settingsService: SettingsService, private notificationService: NotificationService, private plexService: PlexService) { } constructor(private settingsService: SettingsService,
private notificationService: NotificationService,
private plexService: PlexService,
private testerService : TesterService) { }
settings: IPlexSettings; settings: IPlexSettings;
loadedServers: IPlexServerViewModel; // This comes from the api call for the user to select a server loadedServers: IPlexServerViewModel; // This comes from the api call for the user to select a server
@ -26,8 +30,7 @@ export class PlexComponent implements OnInit, OnDestroy {
ngOnInit(): void { ngOnInit(): void {
this.settingsService.getPlex().subscribe(x => { this.settingsService.getPlex().subscribe(x => {
this.settings = x; this.settings = x;
} });
);
} }
requestServers(server: IPlexServer): void { requestServers(server: IPlexServer): void {
@ -55,8 +58,14 @@ export class PlexComponent implements OnInit, OnDestroy {
this.notificationService.success("Success", `Selected ${server.name}!`) this.notificationService.success("Success", `Selected ${server.name}!`)
} }
testPlex() { testPlex(server: IPlexServer) {
// TODO Plex Service this.testerService.plexTest(server).subscribe(x => {
if (x) {
this.notificationService.success("Connected", `Successfully connected to the Plex server ${server.name}!`);
} else {
this.notificationService.error("Connected", `We could not connect to the Plex server ${server.name}!`);
}
});
} }
addTab() { addTab() {
@ -68,11 +77,10 @@ export class PlexComponent implements OnInit, OnDestroy {
} }
removeServer(server: IPlexServer) { removeServer(server: IPlexServer) {
this.notificationService.warning("Disabled", "This feature is currently disabled"); var index = this.settings.servers.indexOf(server, 0);
//var index = this.settings.servers.indexOf(server, 0); if (index > -1) {
//if (index > -1) { this.settings.servers.splice(index, 1);
// this.settings.servers.splice(index, 1); }
//}
} }
loadLibraries(server: IPlexServer) { loadLibraries(server: IPlexServer) {

@ -112,7 +112,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<div> <div>
<button [disabled]="form.invalid" (click)="test()" class="btn btn-primary-outline">Test Connectivity <span id="spinner"></span></button> <button [disabled]="form.invalid" (click)="test(form)" class="btn btn-primary-outline">Test Connectivity <span id="spinner"></span></button>
</div> </div>
</div> </div>

@ -7,6 +7,7 @@ import { IRadarrSettings } from '../../interfaces/ISettings';
import { IRadarrProfile, IRadarrRootFolder, IMinimumAvailability } from '../../interfaces/IRadarr'; import { IRadarrProfile, IRadarrRootFolder, IMinimumAvailability } from '../../interfaces/IRadarr';
import { SettingsService } from '../../services/settings.service'; import { SettingsService } from '../../services/settings.service';
import { RadarrService } from '../../services/applications/radarr.service'; import { RadarrService } from '../../services/applications/radarr.service';
import { TesterService } from '../../services/applications/tester.service';
import { NotificationService } from "../../services/notification.service"; import { NotificationService } from "../../services/notification.service";
@Component({ @Component({
@ -15,8 +16,11 @@ import { NotificationService } from "../../services/notification.service";
}) })
export class RadarrComponent implements OnInit { export class RadarrComponent implements OnInit {
constructor(private settingsService: SettingsService, private radarrService: RadarrService, private notificationService: NotificationService, constructor(private settingsService: SettingsService,
private fb: FormBuilder) { } private radarrService: RadarrService,
private notificationService: NotificationService,
private fb: FormBuilder,
private testerService : TesterService) { }
qualities: IRadarrProfile[]; qualities: IRadarrProfile[];
rootFolders: IRadarrRootFolder[]; rootFolders: IRadarrRootFolder[];
@ -61,7 +65,7 @@ export class RadarrComponent implements OnInit {
{ name: "In Cinemas", value: "InCinemas" }, { name: "In Cinemas", value: "InCinemas" },
{ name: "Physical / Web", value: "Released" }, { name: "Physical / Web", value: "Released" },
{ name: "PreDb", value: "PreDb" }, { name: "PreDb", value: "PreDb" },
] ];
} }
@ -86,14 +90,25 @@ export class RadarrComponent implements OnInit {
}); });
} }
test() { test(form: FormGroup) {
// TODO if (form.invalid) {
this.notificationService.error("Validation", "Please check your entered values");
return;
}
var settings = <IRadarrSettings>form.value;
this.testerService.radarrTest(settings).subscribe(x => {
if (x) {
this.notificationService.success("Connected", "Successfully connected to Radarr!");
} else {
this.notificationService.error("Connected", "We could not connect to Radarr!");
}
});
} }
onSubmit(form: FormGroup) { onSubmit(form: FormGroup) {
if (form.invalid) { if (form.invalid) {
this.notificationService.error("Validation", "Please check your entered values"); this.notificationService.error("Validation", "Please check your entered values");
return return;
} }
var settings = <IRadarrSettings>form.value; var settings = <IRadarrSettings>form.value;

@ -110,7 +110,7 @@
<div class="form-group"> <div class="form-group">
<div> <div>
<button type="button" (click)="test()" class="btn btn-primary-outline">Test Connectivity <span id="spinner"> </span></button> <button type="button" (click)="test(form)" class="btn btn-primary-outline">Test Connectivity <span id="spinner"> </span></button>
</div> </div>
</div> </div>

@ -4,6 +4,9 @@ import "rxjs/add/operator/takeUntil";
import { FormGroup, Validators, FormBuilder } from '@angular/forms'; import { FormGroup, Validators, FormBuilder } from '@angular/forms';
import { ISonarrProfile, ISonarrRootFolder } from '../../interfaces/ISonarr' import { ISonarrProfile, ISonarrRootFolder } from '../../interfaces/ISonarr'
import { TesterService } from '../../services/applications/tester.service';
import { ISonarrSettings } from '../../interfaces/ISettings';
import { SettingsService } from '../../services/settings.service'; import { SettingsService } from '../../services/settings.service';
import { SonarrService } from '../../services/applications/sonarr.service'; import { SonarrService } from '../../services/applications/sonarr.service';
import { NotificationService } from "../../services/notification.service"; import { NotificationService } from "../../services/notification.service";
@ -14,7 +17,10 @@ import { NotificationService } from "../../services/notification.service";
}) })
export class SonarrComponent implements OnInit, OnDestroy { export class SonarrComponent implements OnInit, OnDestroy {
constructor(private settingsService: SettingsService, private sonarrService: SonarrService, private notificationService: NotificationService, constructor(private settingsService: SettingsService,
private sonarrService: SonarrService,
private notificationService: NotificationService,
private testerService : TesterService,
private fb : FormBuilder) { } private fb : FormBuilder) { }
qualities: ISonarrProfile[]; qualities: ISonarrProfile[];
@ -84,14 +90,25 @@ export class SonarrComponent implements OnInit, OnDestroy {
}); });
} }
test() { test(form: FormGroup) {
// TODO if (form.invalid) {
this.notificationService.error("Validation", "Please check your entered values");
return;
}
var settings = <ISonarrSettings>form.value;
this.testerService.sonarrTest(settings).subscribe(x => {
if (x) {
this.notificationService.success("Connected", "Successfully connected to Sonarr!");
} else {
this.notificationService.error("Connected", "We could not connect to Sonarr!");
}
});
} }
onSubmit(form:FormGroup) { onSubmit(form:FormGroup) {
if (form.invalid) { if (form.invalid) {
this.notificationService.error("Validation", "Please check your entered values"); this.notificationService.error("Validation", "Please check your entered values");
return return;
} }
this.settingsService.saveSonarr(form.value) this.settingsService.saveSonarr(form.value)
.takeUntil(this.subscriptions) .takeUntil(this.subscriptions)

@ -1,11 +1,20 @@
using System; using System;
using System.Linq;
using System.Threading.Tasks;
using Hangfire; using Hangfire;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Ombi.Api.Emby;
using Ombi.Api.Plex;
using Ombi.Api.Radarr;
using Ombi.Api.Sonarr;
using Ombi.Attributes; using Ombi.Attributes;
using Ombi.Core.Notifications; using Ombi.Core.Notifications;
using Ombi.Core.Settings.Models.External;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Notifications.Agents; using Ombi.Notifications.Agents;
using Ombi.Notifications.Models; using Ombi.Notifications.Models;
using Ombi.Settings.Settings.Models.External;
using Ombi.Settings.Settings.Models.Notifications; using Ombi.Settings.Settings.Models.Notifications;
namespace Ombi.Controllers.External namespace Ombi.Controllers.External
@ -27,7 +36,8 @@ namespace Ombi.Controllers.External
/// <param name="pushbullet">The pushbullet.</param> /// <param name="pushbullet">The pushbullet.</param>
/// <param name="slack">The slack.</param> /// <param name="slack">The slack.</param>
public TesterController(INotificationService service, IDiscordNotification notification, IEmailNotification emailN, public TesterController(INotificationService service, IDiscordNotification notification, IEmailNotification emailN,
IPushbulletNotification pushbullet, ISlackNotification slack, IPushoverNotification po, IMattermostNotification mm) IPushbulletNotification pushbullet, ISlackNotification slack, IPushoverNotification po, IMattermostNotification mm,
IPlexApi plex, IEmbyApi emby, IRadarrApi radarr, ISonarrApi sonarr, ILogger<TesterController> log)
{ {
Service = service; Service = service;
DiscordNotification = notification; DiscordNotification = notification;
@ -36,6 +46,11 @@ namespace Ombi.Controllers.External
SlackNotification = slack; SlackNotification = slack;
PushoverNotification = po; PushoverNotification = po;
MattermostNotification = mm; MattermostNotification = mm;
PlexApi = plex;
RadarrApi = radarr;
EmbyApi = emby;
SonarrApi = sonarr;
Log = log;
} }
private INotificationService Service { get; } private INotificationService Service { get; }
@ -45,6 +60,11 @@ namespace Ombi.Controllers.External
private ISlackNotification SlackNotification { get; } private ISlackNotification SlackNotification { get; }
private IPushoverNotification PushoverNotification { get; } private IPushoverNotification PushoverNotification { get; }
private IMattermostNotification MattermostNotification { get; } private IMattermostNotification MattermostNotification { get; }
private IPlexApi PlexApi { get; }
private IRadarrApi RadarrApi { get; }
private IEmbyApi EmbyApi { get; }
private ISonarrApi SonarrApi { get; }
private ILogger<TesterController> Log { get; }
/// <summary> /// <summary>
@ -141,5 +161,89 @@ namespace Ombi.Controllers.External
return true; return true;
} }
/// <summary>
/// Checks if we can connect to Plex with the provided settings
/// </summary>
/// <param name="settings"></param>
/// <returns></returns>
[HttpPost("plex")]
public async Task<bool> Plex([FromBody] PlexServers settings)
{
try
{
var result = await PlexApi.GetStatus(settings.PlexAuthToken, settings.FullUri);
return result?.MediaContainer?.version != null;
}
catch (Exception e)
{
Log.LogError(LoggingEvents.Api, e, "Could not test Plex");
return false;
}
}
/// <summary>
/// Checks if we can connect to Emby with the provided settings
/// </summary>
/// <param name="settings"></param>
/// <returns></returns>
[HttpPost("emby")]
public async Task<bool> Emby([FromBody] EmbyServers settings)
{
try
{
var result = await EmbyApi.GetUsers(settings.FullUri, settings.ApiKey);
return result.Any();
}
catch (Exception e)
{
Log.LogError(LoggingEvents.Api, e, "Could not test Emby");
return false;
}
}
/// <summary>
/// Checks if we can connect to Radarr with the provided settings
/// </summary>
/// <param name="settings"></param>
/// <returns></returns>
[HttpPost("radarr")]
public async Task<bool> Radarr([FromBody] RadarrSettings settings)
{
try
{
var result = await RadarrApi.SystemStatus(settings.ApiKey, settings.FullUri);
return result.version != null;
}
catch (Exception e)
{
Log.LogError(LoggingEvents.Api, e, "Could not test Radarr");
return false;
}
}
/// <summary>
/// Checks if we can connect to Sonarr with the provided settings
/// </summary>
/// <param name="settings"></param>
/// <returns></returns>
[HttpPost("sonarr")]
public async Task<bool> Sonarr([FromBody] SonarrSettings settings)
{
try
{
var result = await SonarrApi.SystemStatus(settings.ApiKey, settings.FullUri);
return result.version != null;
}
catch (Exception e)
{
Log.LogError(LoggingEvents.Api, e, "Could not test Sonarr");
return false;
}
}
} }
} }

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using AutoMapper; using AutoMapper;
using Hangfire;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Ombi.Api.Emby; using Ombi.Api.Emby;
@ -12,6 +13,9 @@ using Ombi.Core.Settings;
using Ombi.Core.Settings.Models; using Ombi.Core.Settings.Models;
using Ombi.Core.Settings.Models.External; using Ombi.Core.Settings.Models.External;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Schedule.Jobs;
using Ombi.Schedule.Jobs.Emby;
using Ombi.Schedule.Jobs.Radarr;
using Ombi.Settings.Settings.Models; using Ombi.Settings.Settings.Models;
using Ombi.Settings.Settings.Models.External; using Ombi.Settings.Settings.Models.External;
using Ombi.Settings.Settings.Models.Notifications; using Ombi.Settings.Settings.Models.Notifications;
@ -34,19 +38,30 @@ namespace Ombi.Controllers
/// <param name="resolver">The resolver.</param> /// <param name="resolver">The resolver.</param>
/// <param name="mapper">The mapper.</param> /// <param name="mapper">The mapper.</param>
/// <param name="templateRepo">The templateRepo.</param> /// <param name="templateRepo">The templateRepo.</param>
public SettingsController(ISettingsResolver resolver, IMapper mapper, INotificationTemplatesRepository templateRepo, public SettingsController(ISettingsResolver resolver,
IEmbyApi embyApi) IMapper mapper,
INotificationTemplatesRepository templateRepo,
IEmbyApi embyApi,
IPlexContentCacher cacher,
IEmbyContentCacher embyCacher,
IRadarrCacher radarrCacher)
{ {
SettingsResolver = resolver; SettingsResolver = resolver;
Mapper = mapper; Mapper = mapper;
TemplateRepository = templateRepo; TemplateRepository = templateRepo;
_embyApi = embyApi; _embyApi = embyApi;
_plexContentCacher = cacher;
_embyContentCacher = embyCacher;
_radarrCacher = radarrCacher;
} }
private ISettingsResolver SettingsResolver { get; } private ISettingsResolver SettingsResolver { get; }
private IMapper Mapper { get; } private IMapper Mapper { get; }
private INotificationTemplatesRepository TemplateRepository { get; } private INotificationTemplatesRepository TemplateRepository { get; }
private readonly IEmbyApi _embyApi; private readonly IEmbyApi _embyApi;
private readonly IPlexContentCacher _plexContentCacher;
private readonly IEmbyContentCacher _embyContentCacher;
private readonly IRadarrCacher _radarrCacher;
/// <summary> /// <summary>
/// Gets the Ombi settings. /// Gets the Ombi settings.
@ -66,6 +81,7 @@ namespace Ombi.Controllers
[HttpPost("ombi")] [HttpPost("ombi")]
public async Task<bool> OmbiSettings([FromBody]OmbiSettings ombi) public async Task<bool> OmbiSettings([FromBody]OmbiSettings ombi)
{ {
ombi.Wizard = true;
return await Save(ombi); return await Save(ombi);
} }
@ -97,7 +113,12 @@ namespace Ombi.Controllers
[HttpPost("plex")] [HttpPost("plex")]
public async Task<bool> PlexSettings([FromBody]PlexSettings plex) public async Task<bool> PlexSettings([FromBody]PlexSettings plex)
{ {
return await Save(plex); var result = await Save(plex);
if (result)
{
BackgroundJob.Enqueue(() => _plexContentCacher.CacheContent());
}
return result;
} }
/// <summary> /// <summary>
@ -124,7 +145,12 @@ namespace Ombi.Controllers
var admin = users.FirstOrDefault(x => x.Policy.IsAdministrator); var admin = users.FirstOrDefault(x => x.Policy.IsAdministrator);
server.AdministratorId = admin?.Id; server.AdministratorId = admin?.Id;
} }
return await Save(emby); var result = await Save(emby);
if (result)
{
BackgroundJob.Enqueue(() => _embyContentCacher.Start());
}
return result;
} }
/// <summary> /// <summary>
@ -231,7 +257,12 @@ namespace Ombi.Controllers
[HttpPost("radarr")] [HttpPost("radarr")]
public async Task<bool> RadarrSettings([FromBody]RadarrSettings settings) public async Task<bool> RadarrSettings([FromBody]RadarrSettings settings)
{ {
return await Save(settings); var result = await Save(settings);
if (result)
{
BackgroundJob.Enqueue(() => _radarrCacher.CacheContent());
}
return result;
} }
/// <summary> /// <summary>

Loading…
Cancel
Save