Started on the requests rework #865

pull/1488/head
Jamie.Rees 7 years ago
parent dc9030c2ce
commit 8cf5a4c1fd

@ -41,6 +41,12 @@ after_build:
- copy "%APPVEYOR_BUILD_FOLDER%\src\Ombi.Updater\bin\release\netcoreapp1.1\centos.7-x64\publish\Ombi.Updater.dll" "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp1.1\centos.7-x64\publish\Ombi.Updater.dll"
- copy "%APPVEYOR_BUILD_FOLDER%\src\Ombi.Updater\bin\release\netcoreapp1.1\centos.7-x64\publish\Ombi.Updater.dll" "%APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp1.1\centos.7-x64\publish\Ombi.Updater.exe"
- cmd: >-
dir %APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp1.1\win10-x64\publish
dir %APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp1.1\win10-x64
7z a Ombi_windows.zip %APPVEYOR_BUILD_FOLDER%\src\Ombi\bin\Release\netcoreapp1.1\win10-x64\publish

@ -67,6 +67,5 @@ namespace Ombi.Api.Emby.Models.Media.Tv
public string MediaType { get; set; }
public object[] LockedFields { get; set; }
public bool LockData { get; set; }
}
}

@ -15,5 +15,6 @@ namespace Ombi.Core.Engine.Interfaces
Task<IEnumerable<TvRequests>> SearchTvRequest(string search);
Task<TvRequests> UpdateTvRequest(TvRequests request);
Task<IEnumerable<ChildRequests>> GetAllChldren(int tvId);
}
}

@ -114,6 +114,11 @@ namespace Ombi.Core.Engine
return await allRequests.ToListAsync();
}
public async Task<IEnumerable<ChildRequests>> GetAllChldren(int tvId)
{
return await TvRepository.GetChild().Where(x => x.ParentRequestId == tvId).ToListAsync();
}
public async Task<IEnumerable<TvRequests>> SearchTvRequest(string search)
{
var allRequests = TvRepository.Get();

@ -25,8 +25,9 @@ namespace Ombi.Core.Rule.Rules.Request
{
if (obj.RequestType == RequestType.Movie)
{
var movie = (MovieRequests) obj;
var movieRequests = Movie.Get();
var existing = await movieRequests.FirstOrDefaultAsync(x => x.TheMovieDbId == obj.Id);
var existing = await movieRequests.FirstOrDefaultAsync(x => x.TheMovieDbId == movie.TheMovieDbId);
if (existing != null) // Do we already have a request for this?
{

@ -1,7 +1,29 @@
namespace Ombi.Schedule.Jobs.Emby
using Microsoft.Extensions.Logging;
using Ombi.Api.Emby;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Serilog;
namespace Ombi.Schedule.Jobs.Emby
{
public class EmbyContentCacher
{
public EmbyContentCacher(ISettingsService<EmbySettings> settings, IEmbyApi api, ILogger<EmbyContentCacher> logger)
{
}
private bool ValidateSettings(EmbySettings emby)
{
if (emby.Enable)
{
if (emby?.Ip == null || string.IsNullOrEmpty(emby?.ApiKey))
{
//Log.Warn("A setting is null, Ensure Emby is configured correctly, and we have a Emby Auth token.");
return false;
}
}
return emby.Enable;
}
}
}

@ -13,6 +13,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Api.Emby\Ombi.Api.Emby.csproj" />
<ProjectReference Include="..\Ombi.Api.Plex\Ombi.Api.Plex.csproj" />
<ProjectReference Include="..\Ombi.Api.Radarr\Ombi.Api.Radarr.csproj" />
<ProjectReference Include="..\Ombi.Settings\Ombi.Settings.csproj" />

@ -10,22 +10,12 @@ import { HttpModule } from '@angular/http';
import { ButtonModule, DialogModule } from 'primeng/primeng';
import { GrowlModule } from 'primeng/components/growl/growl';
import { DataTableModule, SharedModule } from 'primeng/primeng';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
//import { DragulaModule, DragulaService } from 'ng2-dragula/ng2-dragula';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
// Components
import { AppComponent } from './app.component';
// Search
// Request
import { RequestComponent } from './requests/request.component';
import { MovieRequestsComponent } from './requests/movierequests.component';
import { TvRequestsComponent } from './requests/tvrequests.component';
//import { RequestGridComponent } from './request-grid/request-grid.component';
import { RequestCardComponent } from './request-grid/request-card.component';
import { LoginComponent } from './login/login.component';
import { LandingPageComponent } from './landingpage/landingpage.component';
import { PageNotFoundComponent } from './errors/not-found.component';
@ -46,11 +36,12 @@ import { SettingsModule } from './settings/settings.module';
import { WizardModule } from './wizard/wizard.module';
import { SearchModule } from './search/search.module';
import { UserManagementModule } from './usermanagement/usermanagement.module';
import { RequestsModule } from './requests/requests.module';
const routes: Routes = [
{ path: '*', component: PageNotFoundComponent },
{ path: '', redirectTo: '/search', pathMatch: 'full' },
{ path: 'requests', component: RequestComponent, canActivate: [AuthGuard] },
//{ path: 'requests-grid', component: RequestGridComponent },
{ path: 'login', component: LoginComponent },
{ path: 'landingpage', component: LandingPageComponent }
@ -68,7 +59,6 @@ const routes: Routes = [
SettingsModule,
DataTableModule,
SharedModule,
InfiniteScrollModule,
AuthModule,
WizardModule,
SearchModule,
@ -80,18 +70,14 @@ const routes: Routes = [
MdInputModule,
MdTabsModule,
ReactiveFormsModule,
UserManagementModule
UserManagementModule,
RequestsModule
],
declarations: [
AppComponent,
PageNotFoundComponent,
RequestComponent,
LoginComponent,
LandingPageComponent,
MovieRequestsComponent,
TvRequestsComponent,
//RequestGridComponent,
RequestCardComponent,
],
providers: [
RequestService,

@ -0,0 +1,54 @@
import { NgModule, } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
import { ButtonModule, DialogModule } from 'primeng/primeng';
// Request
import { RequestComponent } from './request.component';
import { MovieRequestsComponent } from './movierequests.component';
import { TvRequestsComponent } from './tvrequests.component';
import { TvRequestManageComponent } from './tvrequest-manage.component';
//import { RequestGridComponent } from '../request-grid/request-grid.component';
// import { RequestCardComponent } from '../request-grid/request-card.component';
import { IdentityService } from '../services/identity.service';
import { RequestService } from '../services/request.service';
import { AuthGuard } from '../auth/auth.guard';
const routes: Routes = [
{ path: 'requests', component: RequestComponent, canActivate: [AuthGuard] },
{ path: 'requests/:id', component: TvRequestManageComponent, canActivate: [AuthGuard] },
];
@NgModule({
imports: [
CommonModule,
FormsModule,
RouterModule.forChild(routes),
NgbModule.forRoot(),
InfiniteScrollModule,
ButtonModule,
DialogModule,
],
declarations: [
RequestComponent,
MovieRequestsComponent,
TvRequestsComponent,
TvRequestManageComponent,
],
exports: [
RouterModule
],
providers: [
IdentityService,
RequestService
],
})
export class RequestsModule { }

@ -0,0 +1,9 @@
<div *ngIf="childRequests">
<div *ngFor="let child of childRequests">
<div class="col-md-12">
</div>
</div>
</div>

@ -0,0 +1,72 @@
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { RequestService } from '../services/request.service';
import { IdentityService } from '../services/identity.service';
import { IChildRequests } from '../interfaces/IRequestModel';
@Component({
templateUrl: './tvrequest-manage.component.html'
})
export class TvRequestManageComponent {
constructor(private requestService: RequestService, private identityService: IdentityService,
private route: ActivatedRoute) {
this.route.params
.subscribe(params => {
this.tvId = +params['id']; // (+) converts string 'id' to a number
this.requestService.getChildRequests(this.tvId).subscribe(x => {
this.childRequests = x;
});
});
this.isAdmin = this.identityService.hasRole('admin');
}
tvId: number;
childRequests: IChildRequests[];
isAdmin: boolean;
public removeRequest(request: IChildRequests) {
//this.requestService.removeTvRequest(request);
this.removeRequestFromUi(request);
}
public changeAvailability(request: IChildRequests, available: boolean) {
request.available = available;
}
public approve(request: IChildRequests) {
request.approved = true;
request.denied = false;
}
public deny(request: IChildRequests) {
request.approved = false;
request.denied = true;
}
public approveSeasonRequest(request: IChildRequests) {
request.approved = true;
request.denied = false;
// this.requestService.updateTvRequest(this.selectedSeason)
// .subscribe();
}
public denySeasonRequest(request: IChildRequests) {
request.approved = false;
request.denied = true;
// this.requestService.updateTvRequest(this.selectedSeason)
// .subscribe();
}
private removeRequestFromUi(key: IChildRequests) {
var index = this.childRequests.indexOf(key, 0);
if (index > -1) {
this.childRequests.splice(index, 1);
}
}
}

@ -17,7 +17,7 @@
<div class="row">
<div class="col-sm-2">
<img class="img-responsive poster" src="{{request.posterPath}}" alt="poster">
<img class="img-responsive poster" src="{{request.posterPath}}" alt="poster">
</div>
@ -32,240 +32,25 @@
<span>Status: </span>
<span class="label label-success">{{request.status}}</span>
</div>
<div *ngIf="!request.hasChildRequests">
<div>
<span>Request status: </span>
<span *ngIf="request.available" class="label label-success">Available</span>
<span *ngIf="request.approved && !request.available" class="label label-info">Processing Request</span>
<span *ngIf="request.denied" class="label label-danger">Request Denied</span>
<span *ngIf="request.deniedReason" title="{{request.deniedReason}}"><i class="fa fa-info-circle"></i></span>
<span *ngIf="!request.approved && !request.availble && !request.denied" class="label label-warning">Pending Approval</span>
</div>
<div *ngIf="request.denied">
Denied: <i style="color:red;" class="fa fa-check"></i>
</div>
<div>Release Date: {{request.releaseDate | date}}</div>
<br />
<!--{{#if_eq type "tv"}}
{{#if episodes}}
Episodes: <span class="customTooltip" data-tooltip-content="#{{requestId}}toolTipContent"><i class="fa fa-info-circle"></i></span>
{{else}}
<div>@UI.Requests_SeasonsRequested: {{seriesRequested}}</div>
{{/if}}
{{/if_eq}}-->
<div>Requested Date: {{request.requestedDate | date}}</div>
<!--{{#if admin}}
{{#if currentRootPath}}
<div class="{{requestId}}rootPathMain">Root Path: <span id="{{requestId}}currentRootPath">{{currentRootPath}}</span></div>
{{/if}}
{{/if}}
<div>
{{#if_eq issueId 0}}
@*Nothing*@
{{else}}
@UI.Issues_Issue: <a href="@formAction/issues/{{issueId}}"><i class="fa fa-check"></i></a>
{{/if_eq}}
</div>-->
<div>
<span>Request status: </span>
<span *ngIf="request.available" class="label label-success">Available</span>
<span *ngIf="request.approved && !request.available" class="label label-info">Processing Request</span>
<span *ngIf="request.denied" class="label label-danger">Request Denied</span>
<span *ngIf="request.deniedReason" title="{{request.deniedReason}}"><i class="fa fa-info-circle"></i></span>
<span *ngIf="!request.approved && !request.availble && !request.denied" class="label label-warning">Pending Approval</span>
</div>
<!--Child Requests-->
<button type="button" class="btn btn-sm btn-info-outline" (click)="showChildren(request)">Requests</button>
<div>Release Date: {{request.releaseDate | date}}</div>
<br />
<div>Requested Date: {{request.requestedDate | date}}</div>
</div>
<div class="col-sm-3 col-sm-push-3">
<div *ngIf="isAdmin">
<div *ngIf="!request.approved">
<form>
<input name="requestId" type="text" value="{{request.requestId}}" hidden="hidden" />
<div *ngIf="request.hasQualities" class="btn-group btn-split">
<button type="button" (click)="approve(request)" class="btn btn-sm btn-success-outline approve"><i class="fa fa-plus"></i> Approve</button>
<button type="button" class="btn btn-success-outline dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<!--<ul class="dropdown-menu">
{{#each qualities}}
<li><a href="#" class="approve-with-quality" id="{{id}}">{{name}}</a></li>
{{/each}}
</ul>-->
</div>
<button *ngIf="!request.hasQualities" (click)="approve(request)" style="text-align: right" class="btn btn-sm btn-success-outline approve" type="submit"><i class="fa fa-plus"></i> Approve</button>
</form>
<!--<form method="POST" action="@formAction/requests/changeRootFolder{{#if_eq type "tv"}}tv{{else}}movie{{/if_eq}}" id="changeFolder{{requestId}}">
<input name="requestId" type="text" value="{{requestId}}" hidden="hidden"/>
{{#if_eq hasRootFolders true}}
<div class="btn-group btn-split">
<button type="button" class="btn btn-sm btn-success-outline" id="changeRootFolderBtn{{requestId}}" custom-button="{{requestId}}">@*<i class="fa fa-plus"></i>*@ Change Root Folder</button>
<button type="button" class="btn btn-success-outline dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">@UI.Requests_ToggleDropdown</span>
</button>
<ul class="dropdown-menu">
{{#each rootFolders}}
<li><a href="#" class="change-root-folder" id="{{id}}" requestId="{{requestId}}">{{path}}</a></li>
{{/each}}
</ul>
</div>
{{/if_eq}}
</form>-->
<div *ngIf="!request.denied">
<input name="requestId" type="text" value="{{request.requestId}}" hidden="hidden" />
<input name="reason" type="text" hidden="hidden" />
<div class="btn-group-sm btn-split">
<a (click)="deny(request)" class="btn btn-sm btn-danger-outline deny"><i class="fa fa-times"></i> Deny</a>
<a class="btn btn-sm btn-danger-outline dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a class="deny-with-reason" id="denyReason{{request.requestId}}" href="#" data-toggle="modal" data-target="#denyReasonModal">Deny with a reason</a></li>
</ul>
</div>
<div class="btn-group">
<a href="#" class="btn btn-default">Default</a>
<a href="#" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></a>
<ul class="dropdown-menu btn-split">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>
</div>
</div>
<form>
<button (click)="removeRequest(request)" style="text-align: right" class="btn btn-sm btn-danger-outline delete"><i class="fa fa-minus"></i> Remove</button>
</form>
<form>
<button *ngIf="request.available" (click)="changeAvailability(request, false)" style="text-align: right" value="false" class="btn btn-sm btn-info-outline change"><i class="fa fa-minus"></i> Mark Unavailable</button>
<button *ngIf="!request.available" (click)="changeAvailability(request, true)" style="text-align: right" value="true" class="btn btn-sm btn-success-outline change"><i class="fa fa-plus"></i> Mark Available</button>
</form>
</div>
<input name="requestId" type="text" value="{{request.requestId}}" hidden="hidden" />
<div class="dropdown">
<button id="{{request.requestId}}" class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<i class="fa fa-plus"></i> Report Issue
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li><a issue-select="0">@UI.Issues_WrongAudio</a></li>
<li><a issue-select="1">@UI.Issues_NoSubs</a></li>
<li><a issue-select="2">@UI.Issues_WrongContent</a></li>
<li><a issue-select="3">@UI.Issues_Playback</a></li>
<li><a issue-select="4" data-toggle="modal" data-target="#myModal">@UI.Issues_Other</a></li>
</ul>
</div>
<button [routerLink]="[request.id]" style="text-align: right" class="btn btn-sm btn-success-outline" type="submit"><i class="fa fa-plus"></i> View</button>
</div>
</div>
<hr />
</div>
</div>
<p-dialog *ngIf="showChildDialogue" id="dialogOverride" header="{{selectedSeason?.title}}" [(visible)]="showChildDialogue" [contentStyle]="{'overflow':'auto','max-height':'500px'}" [width]="768">
<div class="row" *ngFor="let child of selectedSeason.childRequests">
<div class="col-md-12">
<!--Child Requests-->
<div class="col-md-9">
<span class="col-md-12">Requested By: <b>{{child.requestedUser.username}}</b></span>
<!--<span class="col-md-12" *ngIf="child.requestAll">Requested All Seasons</span>-->
<!--Seasons-->
<span *ngIf="child.approved && !child.available" class="label label-info">Processing Request</span>
<span *ngIf="child.denied" class="label label-danger">Request Denied</span>
<span *ngIf="child.deniedReason" title="{{child.deniedReason}}"><i class="fa fa-info-circle"></i></span>
<span *ngIf="!child.approved && !child.availble && !child.denied" class="label label-warning">Pending Approval</span>
<div class="col-md-12" *ngFor="let seasons of child.seasonRequests">
<span><b>Season: {{seasons.seasonNumber}}</b></span>
<div>
<span>Episodes:</span>
<div *ngFor="let episode of seasons.episodes">
<!--Episodes-->
<span># {{episode.episodeNumber}} | {{episode.title}}</span>
<span *ngIf="episode.available" class="label label-success">Available</span>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<button *ngIf="!child.approved" type="button" (click)="approveSeasonRequest(child)" class="btn btn-sm btn-success-outline" style="text-align: right"><i class="fa fa-plus"></i> Approve</button>
<button *ngIf="child.approved && !child.available" type="button" [disabled]="true" class="btn btn-sm btn-primary-outline" style="text-align: right"><i class="fa fa-plus"></i> Processing</button>
<button *ngIf="!child.approved && !child.available && !child.denied" type="button" (click)="denySeasonRequest(child)" class="btn btn-sm btn-danger-outline" style="text-align: right"><i class="fa fa-plus"></i> Deny</button>
</div>
</div>
<hr />
</div>
</p-dialog>
<!--<div class="modal fade in" *ngIf="showChildDialogue" style="display: block;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" (click)="showChildDialogue=false">&times;</button>
<h4 class="modal-title">{{selectedSeason?.title}}</h4>
</div>
<div class="modal-body">
<div class="row" *ngFor="let child of selectedSeason.childRequests">
<div class="col-md-12">
<div class="col-md-9">
<span class="col-md-12">Requested By: <b>{{child.requestedUser.username}}</b></span>
<span *ngIf="child.approved && !child.available" class="label label-info">Processing Request</span>
<span *ngIf="child.denied" class="label label-danger">Request Denied</span>
<span *ngIf="child.deniedReason" title="{{child.deniedReason}}"><i class="fa fa-info-circle"></i></span>
<span *ngIf="!child.approved && !child.availble && !child.denied" class="label label-warning">Pending Approval</span>
<div class="col-md-12" *ngFor="let seasons of child.seasonRequests">
<span>Season: {{seasons.seasonNumber}}</span>
<span>Episodes:</span>
<div *ngFor="let episode of seasons.episodes">
<span># {{episode.episodeNumber}} | {{episode.title}}</span>
<span *ngIf="episode.available" class="label label-success">Available</span>
</div>
</div>
</div>
<div class="col-md-3">
<button *ngIf="!child.approved" type="button" (click)="approveSeasonRequest(child)" class="btn btn-sm btn-success-outline" style="text-align: right"><i class="fa fa-plus"></i> Approve</button>
<button *ngIf="child.approved && !child.available" type="button" [disabled]="true" class="btn btn-sm btn-primary-outline" style="text-align: right"><i class="fa fa-plus"></i> Processing</button>
<button *ngIf="!child.approved && !child.available && !child.denied" type="button" (click)="denySeasonRequest(child)" class="btn btn-sm btn-danger-outline" style="text-align: right"><i class="fa fa-plus"></i> Deny</button>
</div>
</div>
<hr />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger-outline" (click)="showChildDialogue=false">Close</button>
</div>
</div>
</div>
</div>-->

@ -7,7 +7,7 @@ import { ServiceAuthHelpers } from './service.helpers';
import { IRequestEngineResult } from '../interfaces/IRequestEngineResult';
import { ISearchMovieResult } from '../interfaces/ISearchMovieResult';
import { ISearchTvResult } from '../interfaces/ISearchTvResult';
import { IMovieRequests, ITvRequests, IRequestCountModel, IRequestGrid } from '../interfaces/IRequestModel';
import { IMovieRequests, ITvRequests, IRequestCountModel, IRequestGrid, IChildRequests } from '../interfaces/IRequestModel';
@Injectable()
export class RequestService extends ServiceAuthHelpers {
@ -42,6 +42,11 @@ export class RequestService extends ServiceAuthHelpers {
getTvRequests(count: number, position: number): Observable<ITvRequests[]> {
return this.http.get(`${this.url}tv/${count}/${position}`).map(this.extractData)
.catch(this.handleError);
}
getChildRequests(requestId: number): Observable<IChildRequests[]> {
return this.http.get(`${this.url}tv/${requestId}/child`).map(this.extractData)
.catch(this.handleError);
}
searchTvRequests(search: string): Observable<ITvRequests[]> {

@ -162,6 +162,17 @@ namespace Ombi.Controllers
return await TvRequestEngine.UpdateTvRequest(model);
}
/// <summary>
/// Retuns all children requests for the request id
/// </summary>
/// <param name="requestId">The Request Id</param>
/// <returns></returns>
[HttpGet("tv/{requestId:int}/child")]
public async Task<IEnumerable<ChildRequests>> GetAllChildren(int requestId)
{
return await TvRequestEngine.GetAllChldren(requestId);
}
/// <summary>
/// Gets the count of total requests
/// </summary>

Loading…
Cancel
Save