Got TV working nicely

This commit is contained in:
tidusjar 2021-03-24 20:57:35 +00:00
parent 62cceb803d
commit 5e6edc2ad8
17 changed files with 176 additions and 123 deletions

View file

@ -67,7 +67,7 @@ namespace Ombi.Core.Engine
$"{movieInfo.Title}{(!string.IsNullOrEmpty(movieInfo.ReleaseDate) ? $" ({DateTime.Parse(movieInfo.ReleaseDate).Year})" : string.Empty)}"; $"{movieInfo.Title}{(!string.IsNullOrEmpty(movieInfo.ReleaseDate) ? $" ({DateTime.Parse(movieInfo.ReleaseDate).Year})" : string.Empty)}";
var userDetails = await GetUser(); var userDetails = await GetUser();
var canRequestOnBehalf = false; var canRequestOnBehalf = model.RequestOnBehalf.HasValue();
var isAdmin = await UserManager.IsInRoleAsync(userDetails, OmbiRoles.PowerUser) || await UserManager.IsInRoleAsync(userDetails, OmbiRoles.Admin); var isAdmin = await UserManager.IsInRoleAsync(userDetails, OmbiRoles.PowerUser) || await UserManager.IsInRoleAsync(userDetails, OmbiRoles.Admin);
if (model.RequestOnBehalf.HasValue() && !isAdmin) if (model.RequestOnBehalf.HasValue() && !isAdmin)

View file

@ -140,7 +140,7 @@ namespace Ombi.Core.Engine
ErrorMessage = "This has already been requested" ErrorMessage = "This has already been requested"
}; };
} }
return await AddExistingRequest(tvBuilder.ChildRequest, existingRequest, tv.RequestOnBehalf); return await AddExistingRequest(tvBuilder.ChildRequest, existingRequest, tv.RequestOnBehalf, tv.RootFolderOverride.GetValueOrDefault(), tv.QualityPathOverride.GetValueOrDefault());
} }
// This is a new request // This is a new request
@ -151,13 +151,10 @@ namespace Ombi.Core.Engine
public async Task<RequestEngineResult> RequestTvShow(TvRequestViewModelV2 tv) public async Task<RequestEngineResult> RequestTvShow(TvRequestViewModelV2 tv)
{ {
var user = await GetUser(); var user = await GetUser();
var canRequestOnBehalf = false; var canRequestOnBehalf = tv.RequestOnBehalf.HasValue();
if (tv.RequestOnBehalf.HasValue()) var isAdmin = await UserManager.IsInRoleAsync(user, OmbiRoles.PowerUser) || await UserManager.IsInRoleAsync(user, OmbiRoles.Admin);
{ if (tv.RequestOnBehalf.HasValue() && !isAdmin)
canRequestOnBehalf = await UserManager.IsInRoleAsync(user, OmbiRoles.PowerUser) || await UserManager.IsInRoleAsync(user, OmbiRoles.Admin);
if (!canRequestOnBehalf)
{ {
return new RequestEngineResult return new RequestEngineResult
{ {
@ -166,6 +163,15 @@ namespace Ombi.Core.Engine
ErrorMessage = $"You do not have the correct permissions to request on behalf of users!" ErrorMessage = $"You do not have the correct permissions to request on behalf of users!"
}; };
} }
if ((tv.RootFolderOverride.HasValue || tv.QualityPathOverride.HasValue) && !isAdmin)
{
return new RequestEngineResult
{
Result = false,
Message = "You do not have the correct permissions!",
ErrorMessage = $"You do not have the correct permissions!"
};
} }
var tvBuilder = new TvShowRequestBuilderV2(MovieDbApi); var tvBuilder = new TvShowRequestBuilderV2(MovieDbApi);
@ -240,11 +246,11 @@ namespace Ombi.Core.Engine
ErrorMessage = "This has already been requested" ErrorMessage = "This has already been requested"
}; };
} }
return await AddExistingRequest(tvBuilder.ChildRequest, existingRequest, tv.RequestOnBehalf); return await AddExistingRequest(tvBuilder.ChildRequest, existingRequest, tv.RequestOnBehalf, tv.RootFolderOverride.GetValueOrDefault(), tv.QualityPathOverride.GetValueOrDefault());
} }
// This is a new request // This is a new request
var newRequest = tvBuilder.CreateNewRequest(tv); var newRequest = tvBuilder.CreateNewRequest(tv, tv.RootFolderOverride.GetValueOrDefault(), tv.QualityPathOverride.GetValueOrDefault());
return await AddRequest(newRequest.NewRequest, tv.RequestOnBehalf); return await AddRequest(newRequest.NewRequest, tv.RequestOnBehalf);
} }
@ -852,10 +858,18 @@ namespace Ombi.Core.Engine
} }
} }
private async Task<RequestEngineResult> AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest, string requestOnBehalf) private async Task<RequestEngineResult> AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest, string requestOnBehalf, int rootFolder, int qualityProfile)
{ {
// Add the child // Add the child
existingRequest.ChildRequests.Add(newRequest); existingRequest.ChildRequests.Add(newRequest);
if (qualityProfile > 0)
{
existingRequest.QualityOverride = qualityProfile;
}
if (rootFolder > 0)
{
existingRequest.RootFolder = rootFolder;
}
await TvRepository.Update(existingRequest); await TvRepository.Update(existingRequest);

View file

@ -217,7 +217,7 @@ namespace Ombi.Core.Helpers
} }
public TvShowRequestBuilderV2 CreateNewRequest(TvRequestViewModelV2 tv) public TvShowRequestBuilderV2 CreateNewRequest(TvRequestViewModelV2 tv, int rootPathOverride, int qualityOverride)
{ {
int.TryParse(TheMovieDbRecord.ExternalIds?.TvDbId, out var tvdbId); int.TryParse(TheMovieDbRecord.ExternalIds?.TvDbId, out var tvdbId);
NewRequest = new TvRequests NewRequest = new TvRequests
@ -232,7 +232,9 @@ namespace Ombi.Core.Helpers
TvDbId = tvdbId, TvDbId = tvdbId,
ChildRequests = new List<ChildRequests>(), ChildRequests = new List<ChildRequests>(),
TotalSeasons = tv.Seasons.Count(), TotalSeasons = tv.Seasons.Count(),
Background = BackdropPath Background = BackdropPath,
RootFolder = rootPathOverride,
QualityOverride = qualityOverride
}; };
NewRequest.ChildRequests.Add(ChildRequest); NewRequest.ChildRequests.Add(ChildRequest);

View file

@ -208,6 +208,10 @@ namespace Ombi.Core.Senders
{ {
qualityToUse = model.ParentRequest.QualityOverride.Value; qualityToUse = model.ParentRequest.QualityOverride.Value;
} }
if (model.ParentRequest.RootFolder.HasValue)
{
rootFolderPath = await GetSonarrRootPath(model.ParentRequest.RootFolder.Value, s);
}
// Are we using v3 sonarr? // Are we using v3 sonarr?
var sonarrV3 = s.V3; var sonarrV3 = s.V3;

View file

@ -5,7 +5,7 @@
</div> </div>
<div *ngIf="discoverResults" class="row full-height"> <div *ngIf="discoverResults" class="row full-height">
<div class="col-xl-2 col-lg-3 col-md-3 col-6 col-sm-4 small-padding" *ngFor="let result of discoverResults"> <div class="col-xl-2 col-lg-3 col-md-3 col-6 col-sm-4 small-padding" *ngFor="let result of discoverResults">
<discover-card [result]="result"></discover-card> <discover-card [isAdmin]="isAdmin" [result]="result"></discover-card>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,25 +1,29 @@
import { Component, AfterViewInit } from "@angular/core"; import { Component } from "@angular/core";
import { ActivatedRoute } from "@angular/router"; import { ActivatedRoute } from "@angular/router";
import { SearchV2Service } from "../../../services"; import { SearchV2Service } from "../../../services";
import { IActorCredits } from "../../../interfaces/ISearchTvResultV2"; import { IActorCredits } from "../../../interfaces/ISearchTvResultV2";
import { IDiscoverCardResult } from "../../interfaces"; import { IDiscoverCardResult } from "../../interfaces";
import { RequestType } from "../../../interfaces"; import { RequestType } from "../../../interfaces";
import { AuthService } from "../../../auth/auth.service";
@Component({ @Component({
templateUrl: "./discover-actor.component.html", templateUrl: "./discover-actor.component.html",
styleUrls: ["./discover-actor.component.scss"], styleUrls: ["./discover-actor.component.scss"],
}) })
export class DiscoverActorComponent implements AfterViewInit { export class DiscoverActorComponent {
public actorId: number; public actorId: number;
public actorCredits: IActorCredits; public actorCredits: IActorCredits;
public loadingFlag: boolean; public loadingFlag: boolean;
public isAdmin: boolean;
public discoverResults: IDiscoverCardResult[] = []; public discoverResults: IDiscoverCardResult[] = [];
constructor(private searchService: SearchV2Service, constructor(private searchService: SearchV2Service,
private route: ActivatedRoute) { private route: ActivatedRoute,
private auth: AuthService) {
this.route.params.subscribe((params: any) => { this.route.params.subscribe((params: any) => {
this.actorId = params.actorId; this.actorId = params.actorId;
this.isAdmin = this.auth.isAdmin();
this.loading(); this.loading();
this.searchService.getMoviesByActor(this.actorId).subscribe(res => { this.searchService.getMoviesByActor(this.actorId).subscribe(res => {
this.actorCredits = res; this.actorCredits = res;
@ -28,18 +32,6 @@ export class DiscoverActorComponent implements AfterViewInit {
}); });
} }
public async ngAfterViewInit() {
// this.discoverResults.forEach((result) => {
// this.searchService.getFullMovieDetails(result.id).subscribe(x => {
// result.available = x.available;
// result.approved = x.approved;
// result.rating = x.voteAverage;
// result.requested = x.requested;
// result.url = x.homepage;
// });
// });
}
private createModel() { private createModel() {
this.finishLoading(); this.finishLoading();
this.discoverResults = []; this.discoverResults = [];

View file

@ -118,12 +118,17 @@ export class DiscoverCardComponent implements OnInit {
this.loading = true; this.loading = true;
switch (this.result.type) { switch (this.result.type) {
case RequestType.tvShow: case RequestType.tvShow:
const dia = this.dialog.open(EpisodeRequestComponent, { width: "700px", data: { series: this.tvSearchResult }, panelClass: 'modal-panel' }); const dia = this.dialog.open(EpisodeRequestComponent, { width: "700px", data: { series: this.tvSearchResult, isAdmin: this.isAdmin }, panelClass: 'modal-panel' });
dia.afterClosed().subscribe(x => this.loading = false); dia.afterClosed().subscribe(x => this.loading = false);
return; return;
case RequestType.movie: case RequestType.movie:
if (this.isAdmin) { if (this.isAdmin) {
this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.movie, id: this.result.id }, panelClass: 'modal-panel' }); const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.movie, id: this.result.id }, panelClass: 'modal-panel' });
dialog.afterClosed().subscribe((result) => {
if (result) {
this.result.requested = true;
}
});
} else { } else {
this.requestService.requestMovie({ theMovieDbId: +this.result.id, languageCode: null, requestOnBehalf: null, qualityPathOverride: null, rootFolderOverride: null }).subscribe(x => { this.requestService.requestMovie({ theMovieDbId: +this.result.id, languageCode: null, requestOnBehalf: null, qualityPathOverride: null, rootFolderOverride: null }).subscribe(x => {
if (x.result) { if (x.result) {

View file

@ -15,7 +15,7 @@
</div> </div>
<div *ngIf="discoverResults" class="row full-height"> <div *ngIf="discoverResults" class="row full-height">
<div class="col-xl-2 col-lg-3 col-md-3 col-6 col-sm-4 small-padding" *ngFor="let result of discoverResults"> <div class="col-xl-2 col-lg-3 col-md-3 col-6 col-sm-4 small-padding" *ngFor="let result of discoverResults">
<discover-card [result]="result"></discover-card> <discover-card [isAdmin]="isAdmins" [result]="result"></discover-card>
</div> </div>
</div> </div>
</div> </div>

View file

@ -4,6 +4,7 @@ import { SearchV2Service, RequestService, MessageService } from "../../../servic
import { IMovieCollectionsViewModel } from "../../../interfaces/ISearchTvResultV2"; import { IMovieCollectionsViewModel } from "../../../interfaces/ISearchTvResultV2";
import { IDiscoverCardResult } from "../../interfaces"; import { IDiscoverCardResult } from "../../interfaces";
import { RequestType } from "../../../interfaces"; import { RequestType } from "../../../interfaces";
import { AuthService } from "../../../auth/auth.service";
@Component({ @Component({
templateUrl: "./discover-collections.component.html", templateUrl: "./discover-collections.component.html",
@ -14,13 +15,15 @@ export class DiscoverCollectionsComponent implements OnInit {
public collectionId: number; public collectionId: number;
public collection: IMovieCollectionsViewModel; public collection: IMovieCollectionsViewModel;
public loadingFlag: boolean; public loadingFlag: boolean;
public isAdmin: boolean;
public discoverResults: IDiscoverCardResult[] = []; public discoverResults: IDiscoverCardResult[] = [];
constructor(private searchService: SearchV2Service, constructor(private searchService: SearchV2Service,
private route: ActivatedRoute, private route: ActivatedRoute,
private requestService: RequestService, private requestService: RequestService,
private messageService: MessageService) { private messageService: MessageService,
private auth: AuthService) {
this.route.params.subscribe((params: any) => { this.route.params.subscribe((params: any) => {
this.collectionId = params.collectionId; this.collectionId = params.collectionId;
}); });
@ -28,6 +31,7 @@ export class DiscoverCollectionsComponent implements OnInit {
public async ngOnInit() { public async ngOnInit() {
this.loadingFlag = true; this.loadingFlag = true;
this.isAdmin = this.auth.isAdmin();
this.collection = await this.searchService.getMovieCollections(this.collectionId); this.collection = await this.searchService.getMovieCollections(this.collectionId);
this.createModel(); this.createModel();
} }

View file

@ -89,15 +89,27 @@ export class MovieDetailsComponent {
const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.movie, id: this.movie.id }, panelClass: 'modal-panel' }); const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.movie, id: this.movie.id }, panelClass: 'modal-panel' });
dialog.afterClosed().subscribe(async (result) => { dialog.afterClosed().subscribe(async (result) => {
if (result) { if (result) {
const requestResult = await this.requestService.requestMovie({ theMovieDbId: this.theMovidDbId,
languageCode: null,
qualityPathOverride: result.radarrPathId,
requestOnBehalf: result.username?.id,
rootFolderOverride: result.radarrFolderId, }).toPromise();
if (requestResult.result) {
this.movie.requested = true; this.movie.requested = true;
this.movie.requestId = result.requestId; this.movie.requestId = result.requestId;
this.movieRequest = await this.requestService.getMovieRequest(this.movie.requestId); this.movieRequest = await this.requestService.getMovieRequest(this.movie.requestId);
this.messageService.send(requestResult.message, "Ok");
} else {
this.messageService.send(requestResult.errorMessage, "Ok");
}
} }
}); });
} else { } else {
const result = await this.requestService.requestMovie({ theMovieDbId: this.theMovidDbId, languageCode: null, requestOnBehalf: userId, qualityPathOverride: undefined, rootFolderOverride: undefined }).toPromise(); const result = await this.requestService.requestMovie({ theMovieDbId: this.theMovidDbId, languageCode: null, requestOnBehalf: userId, qualityPathOverride: undefined, rootFolderOverride: undefined }).toPromise();
if (result.result) { if (result.result) {
this.movie.requested = true; this.movie.requested = true;
this.movie.requestId = result.requestId;
this.movieRequest = await this.requestService.getMovieRequest(this.movie.requestId);
this.messageService.send(result.message, "Ok"); this.messageService.send(result.message, "Ok");
} else { } else {
this.messageService.send(result.errorMessage, "Ok"); this.messageService.send(result.errorMessage, "Ok");

View file

@ -45,7 +45,7 @@
<div *ngIf="request"> <div *ngIf="request">
<span class="label">{{'Requests.RequestedBy' | translate }}:</span> <span class="label">{{'Requests.RequestedBy' | translate }}:</span>
{{request.requestedUser.userAlias}} <span id="requestedByInfo">{{request.requestedUser.userAlias}}</span>
</div> </div>
<div *ngIf="request"> <div *ngIf="request">

View file

@ -1,5 +1,5 @@
import { Component, Input } from "@angular/core"; import { Component, Input } from "@angular/core";
import { IChildRequests, IEpisodesRequests, INewSeasonRequests, ISeasonsViewModel, ITvRequestViewModelV2, RequestType } from "../../../../../interfaces"; import { IChildRequests, IEpisodesRequests, INewSeasonRequests, IRequestEngineResult, ISeasonsViewModel, ITvRequestViewModelV2, RequestType } from "../../../../../interfaces";
import { RequestService } from "../../../../../services/request.service"; import { RequestService } from "../../../../../services/request.service";
import { MessageService } from "../../../../../services"; import { MessageService } from "../../../../../services";
import { DenyDialogComponent } from "../../../shared/deny-dialog/deny-dialog.component"; import { DenyDialogComponent } from "../../../shared/deny-dialog/deny-dialog.component";
@ -7,6 +7,7 @@ import { ISearchTvResultV2 } from "../../../../../interfaces/ISearchTvResultV2";
import { MatDialog } from "@angular/material/dialog"; import { MatDialog } from "@angular/material/dialog";
import { SelectionModel } from "@angular/cdk/collections"; import { SelectionModel } from "@angular/cdk/collections";
import { RequestServiceV2 } from "../../../../../services/requestV2.service"; import { RequestServiceV2 } from "../../../../../services/requestV2.service";
import { AdminRequestDialogComponent } from "../../../../../shared/admin-request-dialog/admin-request-dialog.component";
@Component({ @Component({
templateUrl: "./tv-request-grid.component.html", templateUrl: "./tv-request-grid.component.html",
@ -59,38 +60,21 @@ export class TvRequestGridComponent {
viewModel.seasons.push(seasonsViewModel); viewModel.seasons.push(seasonsViewModel);
}); });
if (this.isAdmin) {
const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.tvShow, id: this.tv.id }, panelClass: 'modal-panel' });
dialog.afterClosed().subscribe(async (result) => {
if (result) {
viewModel.requestOnBehalf = result.username?.id;
viewModel.qualityPathOverride = result?.sonarrPathId;
viewModel.rootFolderOverride = result?.sonarrFolderId;
const requestResult = await this.requestServiceV2.requestTv(viewModel).toPromise(); const requestResult = await this.requestServiceV2.requestTv(viewModel).toPromise();
this.postRequest(requestResult);
if (requestResult.result) {
this.notificationService.send(
`Request for ${this.tv.title} has been added successfully`);
debugger;
this.selection.clear();
if (this.tv.firstSeason) {
this.tv.seasonRequests[0].episodes.forEach(ep => {
ep.requested = true;
ep.requestStatus = "Common.PendingApproval";
});
} }
if (this.tv.requestAll) {
this.tv.seasonRequests.forEach(season => {
season.episodes.forEach(ep => {
ep.requested = true;
ep.requestStatus = "Common.PendingApproval";
}); });
});
}
if (this.tv.latestSeason) {
this.tv.seasonRequests[this.tv.seasonRequests.length - 1].episodes.forEach(ep => {
ep.requested = true;
ep.requestStatus = "Common.PendingApproval";
});
}
} else { } else {
this.notificationService.send(requestResult.errorMessage ? requestResult.errorMessage : requestResult.message); const requestResult = await this.requestServiceV2.requestTv(viewModel).toPromise();
this.postRequest(requestResult);
} }
} }
@ -236,4 +220,37 @@ export class TvRequestGridComponent {
} }
return ""; return "";
} }
private postRequest(requestResult: IRequestEngineResult) {
if (requestResult.result) {
this.notificationService.send(
`Request for ${this.tv.title} has been added successfully`);
this.selection.clear();
if (this.tv.firstSeason) {
this.tv.seasonRequests[0].episodes.forEach(ep => {
ep.requested = true;
ep.requestStatus = "Common.PendingApproval";
});
}
if (this.tv.requestAll) {
this.tv.seasonRequests.forEach(season => {
season.episodes.forEach(ep => {
ep.requested = true;
ep.requestStatus = "Common.PendingApproval";
});
});
}
if (this.tv.latestSeason) {
this.tv.seasonRequests[this.tv.seasonRequests.length - 1].episodes.forEach(ep => {
ep.requested = true;
ep.requestStatus = "Common.PendingApproval";
});
}
} else {
this.notificationService.send(requestResult.errorMessage ? requestResult.errorMessage : requestResult.message);
}
}
} }

View file

@ -76,7 +76,7 @@ export class TvDetailsComponent implements OnInit {
} }
public async request(userId: string) { public async request(userId: string) {
this.dialog.open(EpisodeRequestComponent, { width: "800px", data: <EpisodeRequestData> { series: this.tv, requestOnBehalf: userId }, panelClass: 'modal-panel' }) this.dialog.open(EpisodeRequestComponent, { width: "800px", data: <EpisodeRequestData> { series: this.tv, requestOnBehalf: userId, isAdmin: this.isAdmin }, panelClass: 'modal-panel' })
} }
public async issue() { public async issue() {

View file

@ -3,7 +3,8 @@
<form [formGroup]="form" *ngIf="form"> <form [formGroup]="form" *ngIf="form">
<h1 id="advancedOptionsTitle">{{'MediaDetails.AdvancedOptions' | translate }}</h1> <h1 id="advancedOptionsTitle">{{'MediaDetails.AdvancedOptions' | translate }}</h1>
<div class="alert alert-info" role="alert"> <div class="alert alert-info" role="alert">
{{'MediaDetails.AutoApproveOptions' | translate }} <span *ngIf="data.type === RequestType.movie">{{'MediaDetails.AutoApproveOptions' | translate }}</span>
<span *ngIf="data.type === RequestType.tvShow">{{'MediaDetails.AutoApproveOptionsTv' | translate }}</span>
</div> </div>
<div style="max-width: 0; max-height: 0; overflow: hidden;"> <div style="max-width: 0; max-height: 0; overflow: hidden;">
@ -31,7 +32,7 @@
<hr /> <hr />
<!-- Sonarr --> <!-- Sonarr -->
<div *ngIf="data.type === RequestType.tvShow"> <div *ngIf="data.type === RequestType.tvShow && sonarrEnabled">
<div> <div>
<h3>Sonarr Overrides</h3> <h3>Sonarr Overrides</h3>
<mat-form-field appearance="outline" floatLabel=auto> <mat-form-field appearance="outline" floatLabel=auto>

View file

@ -21,12 +21,9 @@ export class AdminRequestDialogComponent implements OnInit {
constructor( constructor(
public dialogRef: MatDialogRef<AdminRequestDialogComponent>, public dialogRef: MatDialogRef<AdminRequestDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: IAdminRequestDialogData, @Inject(MAT_DIALOG_DATA) public data: IAdminRequestDialogData,
private requestServiceV2: RequestServiceV2,
private notificationService: MessageService,
private identityService: IdentityService, private identityService: IdentityService,
private sonarrService: SonarrService, private sonarrService: SonarrService,
private radarrService: RadarrService, private radarrService: RadarrService,
private requestService: RequestService,
private fb: FormBuilder private fb: FormBuilder
) {} ) {}
@ -38,7 +35,7 @@ export class AdminRequestDialogComponent implements OnInit {
public userId: string; public userId: string;
public radarrEnabled: boolean; public radarrEnabled: boolean;
public sonarrEnabled: boolean;
public sonarrProfiles: ISonarrProfile[]; public sonarrProfiles: ISonarrProfile[];
public sonarrRootFolders: ISonarrRootFolder[]; public sonarrRootFolders: ISonarrRootFolder[];
@ -63,6 +60,8 @@ export class AdminRequestDialogComponent implements OnInit {
); );
if (this.data.type === RequestType.tvShow) { if (this.data.type === RequestType.tvShow) {
this.sonarrEnabled = await this.sonarrService.isEnabled();
if (this.sonarrEnabled) {
this.sonarrService.getQualityProfilesWithoutSettings().subscribe(c => { this.sonarrService.getQualityProfilesWithoutSettings().subscribe(c => {
this.sonarrProfiles = c; this.sonarrProfiles = c;
}); });
@ -70,6 +69,7 @@ export class AdminRequestDialogComponent implements OnInit {
this.sonarrRootFolders = c; this.sonarrRootFolders = c;
}); });
} }
}
if (this.data.type === RequestType.movie) { if (this.data.type === RequestType.movie) {
this.radarrEnabled = await this.radarrService.isRadarrEnabled(); this.radarrEnabled = await this.radarrService.isRadarrEnabled();
if (this.radarrEnabled) { if (this.radarrEnabled) {
@ -102,29 +102,10 @@ export class AdminRequestDialogComponent implements OnInit {
public async submitRequest() { public async submitRequest() {
const model = this.form.value; const model = this.form.value;
if (this.data.type === RequestType.movie) {
this.requestService.requestMovie({
qualityPathOverride: model.radarrPathId,
requestOnBehalf: model.username?.id,
rootFolderOverride: model.radarrFolderId,
theMovieDbId: this.data.id,
languageCode: null
}).subscribe((x) => {
if (x.result) {
this.notificationService.send(x.message, "Ok");
model.radarrQualityOverrideTitle = this.radarrProfiles?.filter(x => x.id == model.radarrPathId)[0]?.name; model.radarrQualityOverrideTitle = this.radarrProfiles?.filter(x => x.id == model.radarrPathId)[0]?.name;
model.radarrRootFolderTitle = this.radarrRootFolders?.filter(x => x.id == model.radarrFolderId)[0]?.path; model.radarrRootFolderTitle = this.radarrRootFolders?.filter(x => x.id == model.radarrFolderId)[0]?.path;
model.sonarrRootFolderTitle = this.sonarrRootFolders?.filter(x => x.id == model.sonarrFolderId)[0]?.path;
model.requestId = x.requestId; model.sonarrQualityOverrideTitle = this.sonarrProfiles?.filter(x => x.id == model.sonarrPathId)[0]?.name;
this.dialogRef.close(model); this.dialogRef.close(model);
} else {
this.notificationService.send(x.errorMessage, "Ok");
}
})
}
} }
} }

View file

@ -1,13 +1,15 @@
import { Component, Inject } from "@angular/core"; import { Component, Inject } from "@angular/core";
import { MatCheckboxChange } from "@angular/material/checkbox"; import { MatCheckboxChange } from "@angular/material/checkbox";
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog";
import { ISearchTvResultV2 } from "../../interfaces/ISearchTvResultV2"; import { ISearchTvResultV2 } from "../../interfaces/ISearchTvResultV2";
import { MessageService } from "../../services"; import { MessageService } from "../../services";
import { ISeasonsViewModel, IEpisodesRequests, INewSeasonRequests, ITvRequestViewModelV2 } from "../../interfaces"; import { ISeasonsViewModel, IEpisodesRequests, INewSeasonRequests, ITvRequestViewModelV2, IRequestEngineResult, RequestType } from "../../interfaces";
import { RequestServiceV2 } from "../../services/requestV2.service"; import { RequestServiceV2 } from "../../services/requestV2.service";
import { AdminRequestDialogComponent } from "../admin-request-dialog/admin-request-dialog.component";
export interface EpisodeRequestData { export interface EpisodeRequestData {
series: ISearchTvResultV2; series: ISearchTvResultV2;
isAdmin: boolean;
requestOnBehalf: string | undefined; requestOnBehalf: string | undefined;
} }
@Component({ @Component({
@ -21,7 +23,7 @@ export class EpisodeRequestComponent {
} }
constructor(public dialogRef: MatDialogRef<EpisodeRequestComponent>, @Inject(MAT_DIALOG_DATA) public data: EpisodeRequestData, constructor(public dialogRef: MatDialogRef<EpisodeRequestComponent>, @Inject(MAT_DIALOG_DATA) public data: EpisodeRequestData,
private requestService: RequestServiceV2, private notificationService: MessageService) { } private requestService: RequestServiceV2, private notificationService: MessageService, private dialog: MatDialog) { }
public async submitRequests() { public async submitRequests() {
@ -57,21 +59,23 @@ export class EpisodeRequestComponent {
viewModel.seasons.push(seasonsViewModel); viewModel.seasons.push(seasonsViewModel);
}); });
if (this.data.isAdmin) {
const dialog = this.dialog.open(AdminRequestDialogComponent, { width: "700px", data: { type: RequestType.tvShow, id: this.data.series.id }, panelClass: 'modal-panel' });
dialog.afterClosed().subscribe(async (result) => {
if (result) {
viewModel.requestOnBehalf = result.username?.id;
viewModel.qualityPathOverride = result?.sonarrPathId;
viewModel.rootFolderOverride = result?.sonarrFolderId;
const requestResult = await this.requestService.requestTv(viewModel).toPromise(); const requestResult = await this.requestService.requestTv(viewModel).toPromise();
this.postRequest(requestResult);
if (requestResult.result) {
this.notificationService.send(
`Request for ${this.data.series.title} has been added successfully`);
this.data.series.seasonRequests.forEach((season) => {
season.episodes.forEach((ep) => {
ep.selected = false;
});
});
} else {
this.notificationService.send(requestResult.errorMessage ? requestResult.errorMessage : requestResult.message);
} }
});
} else {
const requestResult = await this.requestService.requestTv(viewModel).toPromise();
this.postRequest(requestResult);
}
this.dialogRef.close(); this.dialogRef.close();
} }
@ -114,4 +118,20 @@ export class EpisodeRequestComponent {
this.data.series.latestSeason = true; this.data.series.latestSeason = true;
await this.submitRequests(); await this.submitRequests();
} }
private postRequest(requestResult: IRequestEngineResult) {
if (requestResult.result) {
this.notificationService.send(
`Request for ${this.data.series.title} has been added successfully`);
this.data.series.seasonRequests.forEach((season) => {
season.episodes.forEach((ep) => {
ep.selected = false;
});
});
} else {
this.notificationService.send(requestResult.errorMessage ? requestResult.errorMessage : requestResult.message);
}
}
} }

View file

@ -253,6 +253,7 @@
"NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!",
"AdvancedOptions":"Advanced Options", "AdvancedOptions":"Advanced Options",
"AutoApproveOptions":"You can configure the request here, once requested it will be send to your DVR application and will be auto approved!", "AutoApproveOptions":"You can configure the request here, once requested it will be send to your DVR application and will be auto approved!",
"AutoApproveOptionsTv":"You can configure the request here, once requested it will be send to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it!",
"QualityProfilesSelect":"Select A Quality Profile", "QualityProfilesSelect":"Select A Quality Profile",
"RootFolderSelect":"Select A Root Folder", "RootFolderSelect":"Select A Root Folder",
"Status":"Status", "Status":"Status",