More on the search and requests page. It's almost there for movies. Need to add some filtering logic #865

pull/1389/head
tidusjar 8 years ago
parent 4c95b1f70b
commit a21db34d60

@ -11,5 +11,6 @@ namespace Ombi.Core
Task<IEnumerable<SearchMovieViewModel>> ProcessMovieSearch(string search);
Task<IEnumerable<SearchMovieViewModel>> TopRatedMovies();
Task<IEnumerable<SearchMovieViewModel>> UpcomingMovies();
Task<IEnumerable<SearchMovieViewModel>> LookupImdbInformation(IEnumerable<SearchMovieViewModel> movies);
}
}

@ -23,6 +23,57 @@ namespace Ombi.Core.Engine
private IRequestService RequestService { get; }
private IMovieDbApi MovieApi { get; }
public async Task<IEnumerable<SearchMovieViewModel>> LookupImdbInformation(IEnumerable<SearchMovieViewModel> movies)
{
var retVal = new List<SearchMovieViewModel>();
Dictionary<int, RequestModel> dbMovies = await RequestedMovies();
foreach (var m in movies)
{
var movieInfo = await MovieApi.GetMovieInformationWithVideo(m.Id);
var viewMovie = new SearchMovieViewModel
{
Adult = movieInfo.adult,
BackdropPath = movieInfo.backdrop_path,
Id = movieInfo.id,
OriginalLanguage = movieInfo.original_language,
OriginalTitle = movieInfo.original_title,
Overview = movieInfo.overview,
Popularity = movieInfo.popularity,
PosterPath = movieInfo.poster_path,
ReleaseDate =
string.IsNullOrEmpty(movieInfo.release_date)
? DateTime.MinValue
: DateTime.Parse(movieInfo.release_date),
Title = movieInfo.title,
Video = movieInfo.video,
VoteAverage = movieInfo.vote_average,
VoteCount = movieInfo.vote_count,
ImdbId = movieInfo?.imdb_id,
Homepage = movieInfo?.homepage
};
retVal.Add(viewMovie);
// TODO needs to be careful about this, it's adding extra time to search...
// https://www.themoviedb.org/talk/5807f4cdc3a36812160041f2
//var videoId = movieInfo?.video ?? false
// ? movieInfo?.videos?.results?.FirstOrDefault()?.key
// : string.Empty;
//viewMovie.Trailer = string.IsNullOrEmpty(videoId)
// ? string.Empty
// : $"https://www.youtube.com/watch?v={videoId}";
if (dbMovies.ContainsKey(movieInfo.id) /*&& canSee*/) // compare to the requests db
{
var dbm = dbMovies[movieInfo.id];
viewMovie.Requested = true;
viewMovie.Approved = dbm.Approved;
viewMovie.Available = dbm.Available;
}
}
return retVal;
}
public async Task<IEnumerable<SearchMovieViewModel>> ProcessMovieSearch(string search)
{
var api = new TheMovieDbApi.TheMovieDbApi();
@ -103,25 +154,7 @@ namespace Ombi.Core.Engine
};
viewMovies.Add(viewMovie);
var counter = 0;
if (counter <= 5) // Let's only do it for the first 5 items
{
var movieInfo = await MovieApi.GetMovieInformationWithVideo(movie.id);
// TODO needs to be careful about this, it's adding extra time to search...
// https://www.themoviedb.org/talk/5807f4cdc3a36812160041f2
viewMovie.ImdbId = movieInfo?.imdb_id;
viewMovie.Homepage = movieInfo?.homepage;
//var videoId = movieInfo?.video ?? false
// ? movieInfo?.videos?.results?.FirstOrDefault()?.key
// : string.Empty;
//viewMovie.Trailer = string.IsNullOrEmpty(videoId)
// ? string.Empty
// : $"https://www.youtube.com/watch?v={videoId}";
counter++;
}
// var canSee = CanUserSeeThisRequest(viewMovie.Id, Security.HasPermissions(User, Permissions.UsersCanViewOnlyOwnRequests), dbMovies);

@ -257,6 +257,22 @@ namespace Ombi.Core.Engine
var allRequests = await RequestService.GetAllAsync();
var results = allRequests.FirstOrDefault(x => x.Id == request.Id);
results.Approved = request.Approved;
results.Available = request.Available;
results.Denied = request.Denied;
results.DeniedReason = request.DeniedReason;
//results.AdminNote = request.AdminNote;
results.ImdbId = request.ImdbId;
results.Episodes = request.Episodes?.ToList() ?? new List<EpisodesModel>();
results.IssueId = request.IssueId;
//results.Issues = request.Issues;
//results.OtherMessage = request.OtherMessage;
results.Overview = request.Overview;
results.PosterPath = request.PosterPath;
results.RequestedUsers = request.RequestedUsers?.ToList() ?? new List<string>();
//results.RootFolderSelected = request.RootFolderSelected;
var model = RequestService.UpdateRequest(results);
return MapToVm(new List<RequestModel>{model}).FirstOrDefault();
}

@ -23,6 +23,12 @@ namespace Ombi.Controllers
return await MovieEngine.ProcessMovieSearch(searchTerm);
}
[HttpPost("movie/extrainfo")]
public async Task<IEnumerable<SearchMovieViewModel>> GetImdbInfo([FromBody]IEnumerable<SearchMovieViewModel> model)
{
return await MovieEngine.LookupImdbInformation(model);
}
[HttpGet("movie/popular")]
public async Task<IEnumerable<SearchMovieViewModel>> Popular()
{

@ -692,7 +692,7 @@ $border-radius: 10px;
// Bootstrap overrides
html {
font-size: 10px;
font-size: 16px;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
body {

@ -32,6 +32,7 @@ var paths = {
'@angular/http',
'@angular/router',
'@angular/forms',
],
dest: './lib'
},
@ -122,7 +123,7 @@ var paths = {
{
name: "angular2-infinite-scroll",
src: ['./node_modules/angular2-infinite-scroll/**/*.js', '!./node_modules/angular2-infinite-scroll/bundles/**/*.js'],
dest:"./lib/angular2-infinite-scroll/"
dest: "./lib/angular2-infinite-scroll/"
},
],
sass: { // Simple sass->css compilation
@ -273,11 +274,17 @@ gulp.task('typescript', function () {
return run('tsc').exec();
});
uglify().on('error',
function(err) {
gutil.log(gutil.colors.red('[Error]'), err.toString());
this.emit('end');
});
gulp.task('fullvar', () => { global.full = true });
gulp.task('copy', ['lib', 'libcss', 'libfonts', 'libimages', 'npm', 'modules']);
gulp.task('compile', callback => runSequence('copy', 'sass', callback));
gulp.task('build', callback => runSequence('compile', 'bundle', callback));
gulp.task('full', callback => runSequence('clean', 'compile', callback));
gulp.task('full', callback => runSequence(/*'clean',*/ 'compile', callback));
// Use this in a build server environment to compile and bundle everything
gulp.task('publish', callback => runSequence('fullvar', 'full', 'typescript', 'bundle', callback));

@ -17,6 +17,7 @@
"@types/jquery": "^2.0.33",
"@types/systemjs": "^0.20.2",
"angular2-infinite-scroll": "^0.3.4",
"angular2-moment": "^1.3.3",
"bootstrap": "3.3.6",
"core-js": "^2.4.1",
"del": "^2.2.2",

@ -14,13 +14,13 @@
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a [routerLink]="['/search']"><i class="fa fa-search"></i> Search</a></li>
<li><a [routerLinkActive]="['active']" [routerLink]="['/search']"><i class="fa fa-search"></i> Search</a></li>
</ul>
<ul class="nav navbar-nav">
<li><a [routerLink]="['/requests']"><i class="fa fa-plus"></i> Requests</a></li>
<li><a [routerLinkActive]="['active']" [routerLink]="['/requests']"><i class="fa fa-plus"></i> Requests</a></li>
</ul>
<ul class="nav navbar-nav">
<li><a [routerLink]="['/Settings/Ombi']"><i class="fa fa-cog"></i> Settings</a></li>
<li><a [routerLinkActive]="['active']" [routerLink]="['/Settings/Ombi']"><i class="fa fa-cog"></i> Settings</a></li>
</ul>
</div>
</div>

@ -1,5 +1,5 @@
<h1 id="searchTitle">Requests</h1>
<h4>Below you can see yours and all other requests, as well as their download and approval status.</h4>
<div class="form-group">
<div>
<input type="text" class="form-control form-control-custom" placeholder="Search" (keyup)="search($event)">
@ -26,8 +26,8 @@
<div class="col-sm-5 ">
<div>
<a href="http://www.imdb.com/title/{{request.imdb}}/" target="_blank">
<h4 class="request-title">{{request.title}} ({{request.releaseDate | date: yyyy}})</h4>
<a href="http://www.imdb.com/title/{{request.imdbId}}/" target="_blank">
<h4 class="request-title">{{request.title}} ({{request.releaseDate | date: 'yyyy'}})</h4>
</a>
</div>
<br />
@ -38,11 +38,11 @@
<div>
<span>Request status: </span>
<span *ngIf="request.available" class="label label-success">Request Available</span>
<span *ngIf="request.approved" class="label label-info">Processing Request</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" class="label label-warning">Pending Approval</span>
<span *ngIf="!request.approved && !request.availble && !request.denied" class="label label-warning">Pending Approval</span>
</div>
<div *ngIf="request.denied">
@ -51,8 +51,8 @@
</div>
<div>Release Date: {{request.releaseDate}}</div>
<div>Release Date: {{request.releaseDate | date}}</div>
<br/>
<!--{{#if_eq type "tv"}}
{{#if episodes}}
@ -64,7 +64,7 @@
{{/if_eq}}-->
<div *ngIf="request.requestedUsers">Requested By: {{request.requestedUsers}}</div>
<div>Requested Date: {{request.requestedDate}}</div>
<div>Requested Date: {{request.requestedDate | date}}</div>
<!--{{#if admin}}
{{#if currentRootPath}}
<div class="{{requestId}}rootPathMain">Root Path: <span id="{{requestId}}currentRootPath">{{currentRootPath}}</span></div>
@ -88,72 +88,77 @@
<div class="col-sm-3 col-sm-push-3">
<div *ngIf="!request.admin">
<div *ngIf="!request.approved">
<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">
<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>
</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>
<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" />
<input name="requestId" type="text" value="{{requestId}}" hidden="hidden"/>
{{#if_eq hasRootFolders true}}
<div class="btn-group btn-split">
<button type="button" (click)="deny(request)" class="btn btn-sm btn-danger-outline deny"><i class="fa fa-times"></i> Deny</button>
<button type="button" class="btn btn-danger-outline dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<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">
<li><a class="deny-with-reason" id="denyReason{{request.requestId}}" href="#" data-toggle="modal" data-target="#denyReasonModal">Deny with a reason</a></li>
{{#each rootFolders}}
<li><a href="#" class="change-root-folder" id="{{id}}" requestId="{{requestId}}">{{path}}</a></li>
{{/each}}
</ul>
</div>
</div>
</div>
{{/if_eq}}
</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>
<button *ngIf="request.available" (click)="changeAvailability(request, true)" 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, false)" style="text-align: right" value="true" class="btn btn-sm btn-success-outline change"><i class="fa fa-plus"></i> Mark Available</button>
<div *ngIf="!request.denied">
<form>
<input name="requestId" type="text" value="{{request.requestId}}" hidden="hidden"/>
<input name="reason" type="text" hidden="hidden"/>
<div class="btn-group btn-split">
<button type="button" (click)="deny(request)" class="btn btn-sm btn-danger-outline deny"><i class="fa fa-times"></i> Deny</button>
<button type="button" class="btn btn-danger-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">
<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>
</form>
</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>
</div>
<input name="requestId" type="text" value="{{request.requestId}}" hidden="hidden" />
@ -163,11 +168,11 @@
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li><a id="{{request.requestId}}" issue-select="0" class="dropdownIssue" href="#">@UI.Issues_WrongAudio</a></li>
<li><a id="{{request.requestId}}" issue-select="1" class="dropdownIssue" href="#">@UI.Issues_NoSubs</a></li>
<li><a id="{{request.requestId}}" issue-select="2" class="dropdownIssue" href="#">@UI.Issues_WrongContent</a></li>
<li><a id="{{request.requestId}}" issue-select="3" class="dropdownIssue" href="#">@UI.Issues_Playback</a></li>
<li><a id="{{request.requestId}}" issue-select="4" class="dropdownIssue" href="#" data-toggle="modal" data-target="#myModal">@UI.Issues_Other</a></li>
<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>

@ -66,11 +66,13 @@ export class RequestComponent implements OnInit {
changeAvailability(request: IRequestModel, available: boolean) {
request.available = available;
this.updateRequest(request);
}
approve(request: IRequestModel) {
request.approved = true;
request.denied = false;
this.updateRequest(request);
}

@ -1,5 +1,5 @@
<h1 id="searchTitle">Search</h1>
<h4>Search Paragraph</h4>
<h4>Want to watch something that is not currently available?! No problem! Just search for it below and request it!</h4>
<br />
<!-- Nav tabs -->
@ -137,17 +137,15 @@
<span *ngIf="result.releaseDate" class="label label-info" target="_blank">Release Date: {{result.releaseDate | date: 'dd/MM/yyyy'}}</span>
<span *ngIf="result.available" class="label label-success">@UI.Search_Available</span>
<span *ngIf="result.approved" class="label label-info">@UI.Search_Processing_Request</span>
<div *ngIf="result.requested; then requested else notRequested"></div>
<span *ngIf="result.available" class="label label-success">Available</span>
<span *ngIf="result.approved && !result.available" class="label label-info">Processing Request</span>
<div *ngIf="result.requested && !result.available; then requested else notRequested"></div>
<template #requested>
<span class="label label-warning">Pending Approval</span>
<span *ngIf="!result.available" class="label label-warning">Pending Approval</span>
</template>
<template #notRequested>
<span class="label label-danger">Not Yet Requested</span>
<span *ngIf="!result.available" class="label label-danger">Not Yet Requested</span>
</template>

@ -33,7 +33,13 @@ export class SearchComponent implements OnInit {
this.clearResults();
return;
}
this.searchService.searchMovie(this.searchText).subscribe(x => this.movieResults = x);
this.searchService.searchMovie(this.searchText).subscribe(x => {
this.movieResults = x;
// Now let's load some exta info including IMDBId
// This way the search is fast at displaying results.
this.getExtaInfo();
});
});
}
@ -66,19 +72,35 @@ export class SearchComponent implements OnInit {
popularMovies() {
this.clearResults();
this.searchService.popularMovies().subscribe(x => this.movieResults = x);
this.searchService.popularMovies().subscribe(x => {
this.movieResults = x;
this.getExtaInfo();
});
}
nowPlayingMovies() {
this.clearResults();
this.searchService.nowPlayingMovies().subscribe(x => this.movieResults = x);
this.searchService.nowPlayingMovies().subscribe(x => {
this.movieResults = x;
this.getExtaInfo();
});
}
topRatedMovies() {
this.clearResults();
this.searchService.topRatedMovies().subscribe(x => this.movieResults = x);
this.searchService.topRatedMovies().subscribe(x => {
this.movieResults = x;
this.getExtaInfo();
});
}
upcomingMovies() {
this.clearResults();
this.searchService.upcomignMovies().subscribe(x => this.movieResults = x);
this.searchService.upcomignMovies().subscribe(x => {
this.movieResults = x;
this.getExtaInfo();
});
}
private getExtaInfo() {
this.searchService.extraInfo(this.movieResults).subscribe(m => this.movieResults = m);
}
private clearResults() {

@ -27,4 +27,7 @@ export class SearchService extends ServiceHelpers {
topRatedMovies(): Observable<ISearchMovieResult[]> {
return this.http.get(`${this.url}/Movie/toprated`).map(this.extractData);
}
extraInfo(movies: ISearchMovieResult[]): Observable<ISearchMovieResult[]> {
return this.http.post(`${this.url}/Movie/extrainfo`, JSON.stringify(movies), { headers: this.headers }).map(this.extractData);
}
}
Loading…
Cancel
Save