#1513 #865 Fixed the issue where we do not send the requests to Radarr/Sonarr when approving

Also fixed a landing page issue
This commit is contained in:
tidusjar 2017-09-23 23:38:18 +01:00
parent 0139a8f514
commit df1ab01e46
13 changed files with 134 additions and 37 deletions

View file

@ -15,5 +15,6 @@ namespace Ombi.Core.Engine.Interfaces
Task RemoveMovieRequest(int requestId); Task RemoveMovieRequest(int requestId);
Task<MovieRequests> UpdateMovieRequest(MovieRequests request); Task<MovieRequests> UpdateMovieRequest(MovieRequests request);
Task<RequestEngineResult> ApproveMovie(MovieRequests request);
} }
} }

View file

@ -20,5 +20,6 @@ namespace Ombi.Core.Engine.Interfaces
Task<IEnumerable<ChildRequests>> GetAllChldren(int tvId); Task<IEnumerable<ChildRequests>> GetAllChldren(int tvId);
Task<ChildRequests> UpdateChildRequest(ChildRequests request); Task<ChildRequests> UpdateChildRequest(ChildRequests request);
Task RemoveTvChild(int requestId); Task RemoveTvChild(int requestId);
Task<RequestEngineResult> ApproveChildRequest(ChildRequests request);
} }
} }

View file

@ -141,6 +141,42 @@ namespace Ombi.Core.Engine
return results; return results;
} }
/// <summary>
/// This is the method that is triggered by pressing Approve on the requests page
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<RequestEngineResult> ApproveMovie(MovieRequests request)
{
if (request.Approved)
{
var result = await Sender.Send(request);
if (result.Success && result.MovieSent)
{
return new RequestEngineResult
{
RequestAdded = true
};
}
if (!result.Success)
{
Logger.LogWarning("Tried auto sending movie but failed. Message: {0}", result.Message);
return new RequestEngineResult
{
Message = result.Message,
ErrorMessage = result.Message,
RequestAdded = false
};
}
// If there are no providers then it's successful but movie has not been sent
}
return new RequestEngineResult
{
RequestAdded = true
};
}
/// <summary> /// <summary>
/// Updates the movie request. /// Updates the movie request.
/// </summary> /// </summary>

View file

@ -159,11 +159,25 @@ namespace Ombi.Core.Engine
var allRequests = TvRepository.Get(); var allRequests = TvRepository.Get();
var results = await allRequests.FirstOrDefaultAsync(x => x.Id == request.Id); var results = await allRequests.FirstOrDefaultAsync(x => x.Id == request.Id);
// TODO need to check if we need to approve any child requests since they may have updated
await TvRepository.Update(results); await TvRepository.Update(results);
return results; return results;
} }
public async Task<RequestEngineResult> ApproveChildRequest(ChildRequests request)
{
if (request.Approved)
{
await Audit.Record(AuditType.Approved, AuditArea.TvRequest, $"Approved Request {request.Title}", Username);
// Autosend
await TvSender.SendToSonarr(request);
}
await TvRepository.UpdateChild(request);
return new RequestEngineResult
{
RequestAdded = true
};
}
public async Task<ChildRequests> UpdateChildRequest(ChildRequests request) public async Task<ChildRequests> UpdateChildRequest(ChildRequests request)
{ {
await Audit.Record(AuditType.Updated, AuditArea.TvRequest, $"Updated Request {request.Title}", Username); await Audit.Record(AuditType.Updated, AuditArea.TvRequest, $"Updated Request {request.Title}", Username);

View file

@ -17,7 +17,7 @@ export interface IPlexLibraries {
export interface IPlexLibResponse { export interface IPlexLibResponse {
successful: boolean; successful: boolean;
message: string; message: string;
data:IPlexLibraries; data: IPlexLibraries;
} }
export interface IMediaContainer { export interface IMediaContainer {

View file

@ -18,7 +18,7 @@
<h3><i class="fa fa-bell-o"></i> <b>Notice</b></h3> <h3><i class="fa fa-bell-o"></i> <b>Notice</b></h3>
<span [innerHtml]="landingPageSettings.noticeText"></span> <span [innerHtml]="landingPageSettings.noticeText"></span>
</div> </div>
<div> <div *ngIf="mediaServerStatus">
<div *ngIf="mediaServerStatus.fullyAvailable"> <div *ngIf="mediaServerStatus.fullyAvailable">
<h3 class="online"><i class="fa fa-check-circle "></i> Currently Online</h3> <h3 class="online"><i class="fa fa-check-circle "></i> Currently Online</h3>
<span>The media server is currently online</span> <span>The media server is currently online</span>

View file

@ -29,6 +29,8 @@ export class LandingPageComponent implements OnInit {
}); });
this.landingPageService.getServerStatus().subscribe(x => this.mediaServerStatus = x); this.landingPageService.getServerStatus().subscribe(x => {
this.mediaServerStatus = x;
});
} }
} }

View file

@ -1,16 +1,11 @@
import { Component, OnDestroy, OnInit } from "@angular/core"; import { Component, OnInit } from "@angular/core";
import "rxjs/add/operator/debounceTime"; import "rxjs/add/operator/debounceTime";
import "rxjs/add/operator/distinctUntilChanged"; import "rxjs/add/operator/distinctUntilChanged";
import "rxjs/add/operator/map"; import "rxjs/add/operator/map";
import "rxjs/add/operator/takeUntil";
import { Subject } from "rxjs/Subject"; import { Subject } from "rxjs/Subject";
import "rxjs/add/operator/debounceTime";
import "rxjs/add/operator/distinctUntilChanged";
import "rxjs/add/operator/map";
import { AuthService } from "../auth/auth.service"; import { AuthService } from "../auth/auth.service";
import { RequestService } from "../services"; import { NotificationService, RequestService } from "../services";
import { IMovieRequests } from "../interfaces"; import { IMovieRequests } from "../interfaces";
@ -18,7 +13,7 @@ import { IMovieRequests } from "../interfaces";
selector: "movie-requests", selector: "movie-requests",
templateUrl: "./movierequests.component.html", templateUrl: "./movierequests.component.html",
}) })
export class MovieRequestsComponent implements OnInit, OnDestroy { export class MovieRequestsComponent implements OnInit {
public movieRequests: IMovieRequests[]; public movieRequests: IMovieRequests[];
public searchChanged: Subject<string> = new Subject<string>(); public searchChanged: Subject<string> = new Subject<string>();
@ -29,14 +24,12 @@ export class MovieRequestsComponent implements OnInit, OnDestroy {
private currentlyLoaded: number; private currentlyLoaded: number;
private amountToLoad: number; private amountToLoad: number;
private subscriptions = new Subject<void>();
constructor(private requestService: RequestService, constructor(private requestService: RequestService,
private auth: AuthService) { private auth: AuthService,
private notificationService: NotificationService) {
this.searchChanged this.searchChanged
.debounceTime(600) // Wait Xms afterthe last event before emitting last event .debounceTime(600) // Wait Xms after the 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
.takeUntil(this.subscriptions)
.subscribe(x => { .subscribe(x => {
this.searchText = x as string; this.searchText = x as string;
if (this.searchText === "") { if (this.searchText === "") {
@ -44,7 +37,6 @@ export class MovieRequestsComponent implements OnInit, OnDestroy {
return; return;
} }
this.requestService.searchMovieRequests(this.searchText) this.requestService.searchMovieRequests(this.searchText)
.takeUntil(this.subscriptions)
.subscribe(m => this.movieRequests = m); .subscribe(m => this.movieRequests = m);
}); });
} }
@ -79,7 +71,7 @@ export class MovieRequestsComponent implements OnInit, OnDestroy {
public approve(request: IMovieRequests) { public approve(request: IMovieRequests) {
request.approved = true; request.approved = true;
request.denied = false; request.denied = false;
this.updateRequest(request); this.approveRequest(request);
} }
public deny(request: IMovieRequests) { public deny(request: IMovieRequests) {
@ -88,14 +80,8 @@ export class MovieRequestsComponent implements OnInit, OnDestroy {
this.updateRequest(request); this.updateRequest(request);
} }
public ngOnDestroy() {
this.subscriptions.next();
this.subscriptions.complete();
}
private loadRequests(amountToLoad: number, currentlyLoaded: number) { private loadRequests(amountToLoad: number, currentlyLoaded: number) {
this.requestService.getMovieRequests(amountToLoad, currentlyLoaded + 1) this.requestService.getMovieRequests(amountToLoad, currentlyLoaded + 1)
.takeUntil(this.subscriptions)
.subscribe(x => { .subscribe(x => {
this.movieRequests.push.apply(this.movieRequests, x); this.movieRequests.push.apply(this.movieRequests, x);
this.currentlyLoaded = currentlyLoaded + amountToLoad; this.currentlyLoaded = currentlyLoaded + amountToLoad;
@ -104,13 +90,25 @@ export class MovieRequestsComponent implements OnInit, OnDestroy {
private updateRequest(request: IMovieRequests) { private updateRequest(request: IMovieRequests) {
this.requestService.updateMovieRequest(request) this.requestService.updateMovieRequest(request)
.takeUntil(this.subscriptions)
.subscribe(x => request = x); .subscribe(x => request = x);
} }
private approveRequest(request: IMovieRequests) {
this.requestService.approveMovie(request)
.subscribe(x => {
if (x.requestAdded) {
this.notificationService.success("Request Approved",
`Request for ${request.title} has been approved successfully`);
} else {
this.notificationService.warning("Request Approved", x.message ? x.message : x.errorMessage);
request.approved = false;
}
});
}
private loadInit() { private loadInit() {
this.requestService.getMovieRequests(this.amountToLoad, 0) this.requestService.getMovieRequests(this.amountToLoad, 0)
.takeUntil(this.subscriptions)
.subscribe(x => this.movieRequests = x); .subscribe(x => this.movieRequests = x);
} }

View file

@ -1,6 +1,6 @@
import { Component, Input } from "@angular/core"; import { Component, Input } from "@angular/core";
import { IChildRequests, IEpisodesRequests } from "../interfaces"; import { IChildRequests, IEpisodesRequests } from "../interfaces";
import { RequestService } from "../services"; import { NotificationService, RequestService } from "../services";
@Component({ @Component({
selector:"tvrequests-children", selector:"tvrequests-children",
@ -9,7 +9,9 @@ import { RequestService } from "../services";
export class TvRequestChildrenComponent { export class TvRequestChildrenComponent {
@Input() public childRequests: IChildRequests[]; @Input() public childRequests: IChildRequests[];
@Input() public isAdmin: boolean; @Input() public isAdmin: boolean;
constructor(private requestService: RequestService ) { } constructor(private requestService: RequestService,
private notificationService: NotificationService) { }
public removeRequest(request: IChildRequests) { public removeRequest(request: IChildRequests) {
this.requestService.deleteChild(request) this.requestService.deleteChild(request)
.subscribe(); .subscribe();
@ -41,8 +43,16 @@ export class TvRequestChildrenComponent {
ep.approved = true; ep.approved = true;
}); });
}); });
this.requestService.updateChild(request) this.requestService.approveChild(request)
.subscribe(); .subscribe(x => {
if (x.requestAdded) {
this.notificationService.success("Request Approved",
`Request has been approved successfully`);
} else {
this.notificationService.warning("Request Approved", x.message ? x.message : x.errorMessage);
request.approved = false;
}
});
} }
public denySeasonRequest(request: IChildRequests) { public denySeasonRequest(request: IChildRequests) {

View file

@ -24,6 +24,10 @@ export class RequestService extends ServiceAuthHelpers {
return this.http.post(`${this.url}TV/`, JSON.stringify(tv), { headers: this.headers }).map(this.extractData); return this.http.post(`${this.url}TV/`, JSON.stringify(tv), { headers: this.headers }).map(this.extractData);
} }
public approveMovie(movie: IMovieRequests): Observable<IRequestEngineResult> {
return this.http.post(`${this.url}Movie/Approve`, JSON.stringify(movie), { headers: this.headers }).map(this.extractData);
}
public getMovieRequests(count: number, position: number): Observable<IMovieRequests[]> { public getMovieRequests(count: number, position: number): Observable<IMovieRequests[]> {
return this.http.get(`${this.url}movie/${count}/${position}`).map(this.extractData); return this.http.get(`${this.url}movie/${count}/${position}`).map(this.extractData);
} }
@ -73,6 +77,9 @@ export class RequestService extends ServiceAuthHelpers {
public updateChild(child: IChildRequests): Observable<IChildRequests> { public updateChild(child: IChildRequests): Observable<IChildRequests> {
return this.http.put(`${this.url}tv/child`, JSON.stringify(child), { headers: this.headers }).map(this.extractData); return this.http.put(`${this.url}tv/child`, JSON.stringify(child), { headers: this.headers }).map(this.extractData);
} }
public approveChild(child: IChildRequests): Observable<IRequestEngineResult> {
return this.http.post(`${this.url}tv/child/approve`, JSON.stringify(child), { headers: this.headers }).map(this.extractData);
}
public deleteChild(child: IChildRequests): Observable<IChildRequests> { public deleteChild(child: IChildRequests): Observable<IChildRequests> {
return this.http.delete(`${this.url}tv/child/${child.id}`, { headers: this.headers }).map(this.extractData); return this.http.delete(`${this.url}tv/child/${child.id}`, { headers: this.headers }).map(this.extractData);
} }

View file

@ -89,6 +89,17 @@ namespace Ombi.Controllers
return await MovieRequestEngine.UpdateMovieRequest(model); return await MovieRequestEngine.UpdateMovieRequest(model);
} }
/// <summary>
/// Updates the specified movie request.
/// </summary>
/// <param name="model">The model.</param>
/// <returns></returns>
[HttpPost("movie/approve")]
public async Task<RequestEngineResult> ApproveMovie([FromBody] MovieRequests model)
{
return await MovieRequestEngine.ApproveMovie(model);
}
/// <summary> /// <summary>
/// Gets the tv requests. /// Gets the tv requests.
/// </summary> /// </summary>
@ -189,6 +200,17 @@ namespace Ombi.Controllers
return await TvRequestEngine.UpdateChildRequest(child); return await TvRequestEngine.UpdateChildRequest(child);
} }
/// <summary>
/// Updates the a specific child request
/// </summary>
/// <param name="child">The model.</param>
/// <returns></returns>
[HttpPost("tv/child/approve")]
public async Task<RequestEngineResult> ApproveChild([FromBody] ChildRequests child)
{
return await TvRequestEngine.ApproveChildRequest(child);
}
/// <summary> /// <summary>
/// Deletes the a specific tv request /// Deletes the a specific tv request
/// </summary> /// </summary>

View file

@ -118,7 +118,7 @@ namespace Ombi.Controllers
public async Task<bool> PlexSettings([FromBody]PlexSettings plex) public async Task<bool> PlexSettings([FromBody]PlexSettings plex)
{ {
var result = await Save(plex); var result = await Save(plex);
if (result) if (result && plex.Enable)
{ {
BackgroundJob.Enqueue(() => _plexContentCacher.CacheContent()); BackgroundJob.Enqueue(() => _plexContentCacher.CacheContent());
} }
@ -142,6 +142,8 @@ namespace Ombi.Controllers
/// <returns></returns> /// <returns></returns>
[HttpPost("emby")] [HttpPost("emby")]
public async Task<bool> EmbySettings([FromBody]EmbySettings emby) public async Task<bool> EmbySettings([FromBody]EmbySettings emby)
{
if (emby.Enable)
{ {
foreach (var server in emby.Servers) foreach (var server in emby.Servers)
{ {
@ -149,8 +151,9 @@ 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;
} }
}
var result = await Save(emby); var result = await Save(emby);
if (result) if (result && emby.Enable)
{ {
BackgroundJob.Enqueue(() => _embyContentCacher.Start()); BackgroundJob.Enqueue(() => _embyContentCacher.Start());
} }

View file

@ -23,6 +23,9 @@
true, true,
"allow-new" "allow-new"
], ],
"no-trailing-whitespace": [
false
],
"max-classes-per-file": [ "max-classes-per-file": [
false false
], ],