more more more !wip

pull/3895/head
TidusJar 6 years ago
parent b570d904bf
commit c18efc5a3a

@ -13,7 +13,7 @@ namespace Ombi.Core.Engine.Interfaces
Task RemoveMovieRequest(int requestId); Task RemoveMovieRequest(int requestId);
Task RemoveAllMovieRequests(); Task RemoveAllMovieRequests();
Task<MovieRequests> GetRequest(int requestId);
Task<MovieRequests> UpdateMovieRequest(MovieRequests request); Task<MovieRequests> UpdateMovieRequest(MovieRequests request);
Task<RequestEngineResult> ApproveMovie(MovieRequests request); Task<RequestEngineResult> ApproveMovie(MovieRequests request);
Task<RequestEngineResult> ApproveMovieById(int requestId); Task<RequestEngineResult> ApproveMovieById(int requestId);

@ -259,6 +259,15 @@ namespace Ombi.Core.Engine
return allRequests; return allRequests;
} }
public async Task<MovieRequests> GetRequest(int requestId)
{
var request = await MovieRepository.GetWithUser().Where(x => x.Id == requestId).FirstOrDefaultAsync();
request.PosterPath = PosterPathHelper.FixPosterPath(request.PosterPath);
await CheckForSubscription(new HideResult(), request);
return request;
}
private async Task CheckForSubscription(HideResult shouldHide, MovieRequests x) private async Task CheckForSubscription(HideResult shouldHide, MovieRequests x)
{ {
if (shouldHide.UserId == x.RequestedUserId) if (shouldHide.UserId == x.RequestedUserId)
@ -493,7 +502,7 @@ namespace Ombi.Core.Engine
RequestType = RequestType.Movie, RequestType = RequestType.Movie,
}); });
return new RequestEngineResult {Result = true, Message = $"{movieName} has been successfully added!", RequestId = model.Id}; return new RequestEngineResult { Result = true, Message = $"{movieName} has been successfully added!", RequestId = model.Id };
} }
public async Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user) public async Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user)
@ -533,7 +542,7 @@ namespace Ombi.Core.Engine
return new RequestQuotaCountModel() return new RequestQuotaCountModel()
{ {
HasLimit = true, HasLimit = true,
Limit = limit, Limit = limit,
Remaining = count, Remaining = count,
NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc), NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc),

@ -157,7 +157,11 @@
} }
.spacing-below { .spacing-below {
margin-bottom: 15px; margin-bottom: 15px !important;
}
.left-seperator {
margin-left:40px;
} }
.tagline { .tagline {

@ -11,6 +11,7 @@ import { TvDetailsComponent } from "./tv/tv-details.component";
import { PipeModule } from "../pipes/pipe.module"; import { PipeModule } from "../pipes/pipe.module";
import { YoutubeTrailerComponent } from "./youtube-trailer.component"; import { YoutubeTrailerComponent } from "./youtube-trailer.component";
import { MovieInformationPanelComponent } from "./movie/panels/movie-information-panel.component"; import { MovieInformationPanelComponent } from "./movie/panels/movie-information-panel.component";
import { TvInformationPanelComponent } from "./tv/panels/tv-information-panel.component";
const routes: Routes = [ const routes: Routes = [
{ path: "movie/:movieDbId", component: MovieDetailsComponent }, { path: "movie/:movieDbId", component: MovieDetailsComponent },
@ -29,6 +30,7 @@ const routes: Routes = [
YoutubeTrailerComponent, YoutubeTrailerComponent,
TvDetailsComponent, TvDetailsComponent,
MovieInformationPanelComponent, MovieInformationPanelComponent,
TvInformationPanelComponent,
], ],
exports: [ exports: [
RouterModule, RouterModule,

@ -67,6 +67,19 @@
<i matTooltip="Instagram" class="fa fa-instagram fa-2x grow"></i> <i matTooltip="Instagram" class="fa fa-instagram fa-2x grow"></i>
</a> </a>
<span class="left-seperator" *ngIf="movie.available">
<a *ngIf="movie.plexUrl" class="media-icons" href="{{movie.plexUrl}}" target="_blank">
<i matTooltip=" {{'Search.ViewOnPlex' | translate}}"
class="fa fa-play-circle fa-2x grow"></i>
</a>
<a *ngIf="movie.embyUrl" class="media-icons" href="{{movie.embyUrl}}" target="_blank">
<i matTooltip=" {{'Search.ViewOnEmby' | translate}}"
class="fa fa-play-circle fa-2x grow"></i>
</a>
</span>
</div> </div>
@ -89,17 +102,9 @@
'Common.Request' | translate }}</button> 'Common.Request' | translate }}</button>
</ng-template> </ng-template>
</span> </span>
<span *ngIf="isAdmin"><button mat-raised-button class="btn-spacing" color="warn" <span *ngIf="isAdmin && hasRequest"><button mat-raised-button class="btn-spacing" color="warn"
(click)="deny()">Deny</button></span> (click)="deny()">{{ 'Requests.Deny' | translate }}</button></span>
<span *ngIf="movie.available">
<a *ngIf="movie.plexUrl" mat-raised-button style="text-align: right"
class="btn-spacing btn-greem" href="{{movie.plexUrl}}" target="_blank"><i
class="fa fa-eye"></i> {{'Search.ViewOnPlex' |
translate}}</a>
<a *ngIf="movie.embyUrl" mat-raised-button class="btn-green btn-spacing"
href="{{movie.embyUrl}}" target="_blank"><i class="fa fa-eye"></i> {{'Search.ViewOnEmby' |
translate}}</a>
</span>
</div> </div>
</div> </div>

@ -6,6 +6,7 @@ import { ISearchMovieResultV2 } from "../../interfaces/ISearchMovieResultV2";
import { MatDialog } from "@angular/material"; import { MatDialog } from "@angular/material";
import { YoutubeTrailerComponent } from "../youtube-trailer.component"; import { YoutubeTrailerComponent } from "../youtube-trailer.component";
import { AuthService } from "../../auth/auth.service"; import { AuthService } from "../../auth/auth.service";
import { IMovieRequests } from "../../interfaces";
@Component({ @Component({
templateUrl: "./movie-details.component.html", templateUrl: "./movie-details.component.html",
@ -14,6 +15,8 @@ import { AuthService } from "../../auth/auth.service";
}) })
export class MovieDetailsComponent { export class MovieDetailsComponent {
public movie: ISearchMovieResultV2; public movie: ISearchMovieResultV2;
public hasRequest: boolean;
public movieRequest: IMovieRequests;
public isAdmin: boolean; public isAdmin: boolean;
private theMovidDbId: number; private theMovidDbId: number;
@ -30,8 +33,13 @@ export class MovieDetailsComponent {
public load() { public load() {
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
this.searchService.getFullMovieDetails(this.theMovidDbId).subscribe(x => { this.searchService.getFullMovieDetails(this.theMovidDbId).subscribe(async x => {
this.movie = x; this.movie = x;
if(this.movie.requestId > 0) {
// Load up this request
this.hasRequest = true;
this.movieRequest = await this.requestService.getMovieRequest(this.movie.requestId);
}
this.imageService.getMovieBanner(this.theMovidDbId.toString()).subscribe(x => { this.imageService.getMovieBanner(this.theMovidDbId.toString()).subscribe(x => {
this.movie.background = this.sanitizer.bypassSecurityTrustStyle this.movie.background = this.sanitizer.bypassSecurityTrustStyle
("url(" + x + ")"); ("url(" + x + ")");
@ -41,7 +49,7 @@ export class MovieDetailsComponent {
} }
public async request() { public async request() {
var result = await this.requestService.requestMovie({ theMovieDbId: this.theMovidDbId, languageCode: null }).toPromise(); const result = await this.requestService.requestMovie({ theMovieDbId: this.theMovidDbId, languageCode: null }).toPromise();
if (result.result) { if (result.result) {
this.movie.requested = true; this.movie.requested = true;
this.messageService.send(result.message, "Ok"); this.messageService.send(result.message, "Ok");
@ -56,4 +64,14 @@ export class MovieDetailsComponent {
data: this.movie.videos.results[0].key data: this.movie.videos.results[0].key
}); });
} }
public async deny() {
const result = await this.requestService.denyMovie({id: this.theMovidDbId, reason: ""}).toPromise();
if (result.result) {
this.movie.approved = false;
this.messageService.send(result.message, "Ok");
} else {
this.messageService.send(result.errorMessage, "Ok");
}
}
} }

@ -1,62 +1,80 @@
<div *ngIf="movie.genres"> <div *ngIf="movie">
<strong>Genres:</strong>
<div>
<mat-chip-list>
<mat-chip *ngFor="let genre of movie.genres">
{{genre.name}}
</mat-chip>
</mat-chip-list>
</div>
</div>
<br />
<div>
<div> <div>
<strong>Status:</strong> <strong>Status:</strong>
<div>{{movie.status}}</div> <div>{{movie.status}}</div>
</div> </div>
<strong>Theatrical Release:</strong>
<div> <div>
{{movie.releaseDate | date: 'mediumDate'}} <strong>Availability</strong>
<div *ngIf="movie.available">{{'Common.Available' | translate}}</div>
<div *ngIf="!movie.available">{{'Common.NotAvailable' | translate}}</div>
</div> </div>
</div>
<div *ngIf="movie.digitalReleaseDate">
<strong>Digital Release:</strong>
<div> <div>
{{movie.digitalReleaseDate | date: 'mediumDate'}} <strong>Request Status</strong>
<div *ngIf="movie.approved && !movie.available">{{'Common.ProcessingRequest' | translate}}</div>
<div *ngIf="movie.requested && !movie.approved && !movie.available">{{'Common.PendingApproval' | translate}}
</div>
<div *ngIf="!movie.requested && !movie.available && !movie.approved">{{'Common.NotRequested' | translate}}
</div>
</div> </div>
</div>
<div *ngIf="movie.voteAverage"> <br />
<strong>User Score:</strong> <div *ngIf="movie.genres">
<div> <strong>Genres:</strong>
{{movie.voteAverage | number:'1.0-1'}} / 10 <div>
<mat-chip-list>
<mat-chip color="accent" selected *ngFor="let genre of movie.genres">
{{genre.name}}
</mat-chip>
</mat-chip-list>
</div>
</div> </div>
</div> <br />
<div *ngIf="movie.voteCount">
<strong>Votes:</strong> <strong>Theatrical Release:</strong>
<div> <div>
{{movie.voteCount | thousandShort: 1}}
</div> {{movie.releaseDate | date: 'mediumDate'}}
</div> <div *ngIf="movie.digitalReleaseDate">
<div> <strong>Digital Release:</strong>
<strong>Runtime:</strong> <div>
<div>{{movie.runtime}} Minutes</div> {{movie.digitalReleaseDate | date: 'mediumDate'}}
</div> </div>
<div *ngIf="movie.revenue"> </div>
<strong>Revenue:</strong> <div *ngIf="movie.voteAverage">
<div> {{movie.revenue | currency: 'USD'}}</div> <strong>User Score:</strong>
</div> <div>
<div *ngIf="movie.budget"> {{movie.voteAverage | number:'1.0-1'}} / 10
<strong>Budget:</strong> </div>
<div> {{movie.budget | currency: 'USD'}}</div> </div>
</div> <div *ngIf="movie.voteCount">
<strong>Votes:</strong>
<div>
{{movie.voteCount | thousandShort: 1}}
</div>
</div>
<div>
<strong>Runtime:</strong>
<div>{{movie.runtime}} Minutes</div>
</div>
<div *ngIf="movie.revenue">
<strong>Revenue:</strong>
<div> {{movie.revenue | currency: 'USD'}}</div>
</div>
<div *ngIf="movie.budget">
<strong>Budget:</strong>
<div> {{movie.budget | currency: 'USD'}}</div>
</div>
<br /> <br />
<div> <div>
<strong>Keywords/Tags:</strong> <strong>Keywords/Tags:</strong>
<mat-chip-list> <mat-chip-list>
<mat-chip *ngFor="let keyword of movie.keywords.keywordsValue"> <mat-chip color="accent" selected *ngFor="let keyword of movie.keywords.keywordsValue">
{{keyword.name}} {{keyword.name}}
</mat-chip> </mat-chip>
</mat-chip-list> </mat-chip-list>
</div> </div>
</div>

@ -0,0 +1,61 @@
<div>
<div *ngIf="tv.status">
<strong>Status:</strong>
<div>
{{tv.status}}
</div>
</div>
<strong>First Aired:</strong>
<div>
{{tv.firstAired | date: 'mediumDate'}}
</div>
</div>
<div>
<strong>Status:</strong>
<div>
{{tv.status}}
</div>
</div>
<div>
<strong>Runtime:</strong>
<div>
{{tv.runtime}} Minutes
</div>
</div>
<div *ngIf="tv.rating">
<strong>Rating:</strong>
<div>
{{tv.rating}} / 10
</div>
</div>
<div *ngIf="tv.network">
<strong>Network:</strong>
<div>
{{tv.network.name}}
</div>
</div>
<div *ngIf="tv.genre">
<strong>Genres:</strong>
<div>
<span *ngFor="let genre of tv.genre">
{{genre}} |
</span>
</div>
</div>
<br />
<div *ngIf="seasonCount">
<strong>Seasons:</strong>
<div>
{{seasonCount}}
</div>
</div>
<div *ngIf="totalEpisodes">
<strong>Episodes:</strong>
<div>
{{totalEpisodes}}
</div>
</div>

@ -0,0 +1,12 @@
import { Component, ViewEncapsulation, Input } from "@angular/core";
import { ISearchTvResultV2 } from "../../../interfaces/ISearchTvResultV2";
@Component({
templateUrl: "./tv-information-panel.component.html",
styleUrls: ["../../media-details.component.scss"],
selector: "tv-information-panel",
encapsulation: ViewEncapsulation.None
})
export class TvInformationPanelComponent {
@Input() public tv: ISearchTvResultV2;
}

@ -79,57 +79,53 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-12 col-md-3"> <div class="col-12 col-md-2">
<mat-card class="card-full mat-elevation-z8"> <mat-card class="mat-elevation-z8">
<mat-card-content> <mat-card-content class="medium-font">
<div> <tv-information-panel [tv]="tv"></tv-information-panel>
<span><strong>First Aired:</strong>
{{tv.firstAired | date: 'mediumDate'}}</span></div>
<div>
<span *ngIf="tv.rating"><strong>Rating:</strong> {{tv.rating}}/10</span>
</div>
<div>
<span><strong>Status:</strong> {{tv.status}}</span>
</div>
<div>
<span><strong>Runtime:</strong> {{tv.runtime}} Minutes</span>
</div>
<div>
<span *ngIf="tv.status"><strong>Status:</strong> {{tv.status}}</span>
</div>
<div>
<span *ngIf="tv.network"><strong>Network:</strong> {{tv.network.name}}</span>
</div>
<div>
<span *ngIf="tv.genre"><strong>Genres:</strong>
<span *ngFor="let genre of tv.genre">
{{genre}} |
</span>
</span>
</div>
<div>
<span *ngIf="seasonCount"><strong>Seasons:</strong> {{seasonCount}}</span>
</div>
<div>
<span *ngIf="totalEpisodes"><strong>Episodes:</strong> {{totalEpisodes}}</span>
</div>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
</div>
</div> <div class="col-12 col-md-10">
<div class="col-12 col-md-9"> <div class="row">
<mat-card class="card-full mat-elevation-z8"> <div class="col-12">
<mat-card-content> <mat-card class="mat-elevation-z8 spacing-below">
{{tv.overview}} <mat-card-content>
</mat-card-content> {{tv.overview}}
</mat-card> </mat-card-content>
</mat-card>
</div>
<div class="col-12">
<mat-card class="mat-elevation-z8 spacing-below">
<mat-card-header>Cast</mat-card-header>
<mat-card-content>
<p-carousel [value]="tv.cast" [numVisible]="5" easing="easeOutStrong">
<ng-template let-item pTemplate="item">
<div class="row justify-content-md-center">
<div class="col-12">
<img class="cast-profile-img" *ngIf="item.character.image.medium"
[src]="item.character.image.medium">
<!-- TODO get profile image default -->
</div>
<div class="col-12">
<span><strong>Character:</strong> {{item.character.name}}</span>
</div>
<div class="col-12">
<span><strong>Actor:</strong> {{item.person.name}}</span>
</div>
</div>
</ng-template>
</p-carousel>
</mat-card-content>
</mat-card>
</div>
</div>
</div> </div>
@ -137,54 +133,10 @@
<div class="row card-spacer media-row"> <div class="row card-spacer media-row">
<!-- <div class="col-12 col-md-3">
<mat-card class="mat-elevation-z8 keywords-panel">
<mat-card-content>
<div>
<span>
<strong>Keywords/Tags:</strong>
<mat-chip-list>
<mat-chip *ngFor="let keyword of tv.keywords.keywordsValue">
{{keyword.name}}
</mat-chip>
</mat-chip-list>
</span>
</div>
</mat-card-content>
</mat-card>
</div> -->
<div class="col-12 col-md-3">
<mat-card class="mat-elevation-z8">
<mat-card-content>
</mat-card-content>
</mat-card>
</div>
<div class="col-12 col-md-9"> <div class="col-12 col-md-9">
<mat-card class="card-full mat-elevation-z8">
<mat-card-header>Cast</mat-card-header>
<mat-card-content>
<p-carousel [value]="tv.cast" [numVisible]="5" easing="easeOutStrong">
<ng-template let-item pTemplate="item">
<div class="row justify-content-md-center">
<div class="col-12">
<img class="cast-profile-img" *ngIf="item.character.image.medium"
[src]="item.character.image.medium">
<!-- TODO get profile image default -->
</div>
<div class="col-12">
<span><strong>Character:</strong> {{item.character.name}}</span>
</div>
<div class="col-12">
<span><strong>Actor:</strong> {{item.person.name}}</span>
</div>
</div>
</ng-template>
</p-carousel>
</mat-card-content>
</mat-card>
</div> </div>
</div> </div>
<div class="row card-spacer media-row"> <div class="row card-spacer media-row">

@ -101,10 +101,10 @@
class="label label-info" [translate]="'Search.Movies.Trailer'"></span></a> class="label label-info" [translate]="'Search.Movies.Trailer'"></span></a>
<span *ngIf="result.quality" id="qualityLabel" class="label label-success">{{result.quality}}p</span> <span *ngIf="result.quality" id="qualityLabel" class="label label-success">{{result.quality}}p</span>
<ng-template [ngIf]="result.available"><span class="label label-success" id="availableLabel" <ng-template [ngIf]="result.available">
[translate]="'Common.Available'"></span></ng-template> <span class="label label-success" id="availableLabel" [translate]="'Common.Available'"></span></ng-template>
<ng-template [ngIf]="result.approved && !result.available"><span class="label label-info" <ng-template [ngIf]="result.approved && !result.available">
id="processingRequestLabel" [translate]="'Common.ProcessingRequest'"></span></ng-template> <span class="label label-info" id="processingRequestLabel" [translate]="'Common.ProcessingRequest'"></span></ng-template>
<ng-template [ngIf]="result.requested && !result.approved && !result.available"><span class="label label-warning" <ng-template [ngIf]="result.requested && !result.approved && !result.available"><span class="label label-warning"
id="pendingApprovalLabel" [translate]="'Common.PendingApproval'"></span></ng-template> id="pendingApprovalLabel" [translate]="'Common.PendingApproval'"></span></ng-template>
<ng-template [ngIf]="!result.requested && !result.available && !result.approved"><span <ng-template [ngIf]="!result.requested && !result.available && !result.approved"><span

@ -70,6 +70,10 @@ export class RequestService extends ServiceHelpers {
return this.http.get<IMovieRequests[]>(`${this.url}movie/search/${search}`, {headers: this.headers}); return this.http.get<IMovieRequests[]>(`${this.url}movie/search/${search}`, {headers: this.headers});
} }
public getMovieRequest(requestId: number): Promise<IMovieRequests> {
return this.http.get<IMovieRequests>(`${this.url}movie/info/${requestId}`, {headers: this.headers}).toPromise();
}
public removeMovieRequest(request: IMovieRequests) { public removeMovieRequest(request: IMovieRequests) {
this.http.delete(`${this.url}movie/${request.id}`, {headers: this.headers}).subscribe(); this.http.delete(`${this.url}movie/${request.id}`, {headers: this.headers}).subscribe();
} }

@ -56,6 +56,16 @@ namespace Ombi.Controllers.V1
}); });
} }
/// <summary>
/// Returns information about the Single Movie Request
/// </summary>
/// <param name="requestId">the movie request id</param>
[HttpGet("movie/info/{requestId}")]
public async Task<MovieRequests> GetMovieRequest(int requestId)
{
return await MovieRequestEngine.GetRequest(requestId);
}
/// <summary> /// <summary>
/// Gets the total amount of movie requests. /// Gets the total amount of movie requests.
/// </summary> /// </summary>

Loading…
Cancel
Save