mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-14 02:26:55 -07:00
Done the movie searching
This commit is contained in:
parent
1c301f2c54
commit
e80f0bc601
16 changed files with 573 additions and 73 deletions
15
Ombi/Ombi.Core/IMovieEngine.cs
Normal file
15
Ombi/Ombi.Core/IMovieEngine.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Models.Search;
|
||||
|
||||
namespace Ombi.Core
|
||||
{
|
||||
public interface IMovieEngine
|
||||
{
|
||||
Task<IEnumerable<SearchMovieViewModel>> NowPlayingMovies();
|
||||
Task<IEnumerable<SearchMovieViewModel>> PopularMovies();
|
||||
Task<IEnumerable<SearchMovieViewModel>> ProcessMovieSearch(string search);
|
||||
Task<IEnumerable<SearchMovieViewModel>> TopRatedMovies();
|
||||
Task<IEnumerable<SearchMovieViewModel>> UpcomingMovies();
|
||||
}
|
||||
}
|
54
Ombi/Ombi.Core/Models/Search/SearchMovieViewModel.cs
Normal file
54
Ombi/Ombi.Core/Models/Search/SearchMovieViewModel.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: SearchMovieViewModel.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.Core.Models.Search
|
||||
{
|
||||
public class SearchMovieViewModel : SearchViewModel
|
||||
{
|
||||
public bool Adult { get; set; }
|
||||
public string BackdropPath { get; set; }
|
||||
public List<int> GenreIds { get; set; }
|
||||
public int Id { get; set; }
|
||||
public string OriginalLanguage { get; set; }
|
||||
public string OriginalTitle { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public double Popularity { get; set; }
|
||||
public string PosterPath { get; set; }
|
||||
public DateTime? ReleaseDate { get; set; }
|
||||
public string Title { get; set; }
|
||||
public bool Video { get; set; }
|
||||
public double VoteAverage { get; set; }
|
||||
public int VoteCount { get; set; }
|
||||
public bool AlreadyInCp { get; set; }
|
||||
public string Trailer { get; set; }
|
||||
public string Homepage { get; set; }
|
||||
public string ImdbId { get; set; }
|
||||
}
|
||||
}
|
36
Ombi/Ombi.Core/Models/Search/SearchViewModel.cs
Normal file
36
Ombi/Ombi.Core/Models/Search/SearchViewModel.cs
Normal file
|
@ -0,0 +1,36 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: SearchViewModel.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
namespace Ombi.Core.Models.Search
|
||||
{
|
||||
public class SearchViewModel
|
||||
{
|
||||
public bool Approved { get; set; }
|
||||
public bool Requested { get; set; }
|
||||
public bool Available { get; set; }
|
||||
public string PlexUrl { get; set; }
|
||||
}
|
||||
}
|
163
Ombi/Ombi.Core/MovieEngine.cs
Normal file
163
Ombi/Ombi.Core/MovieEngine.cs
Normal file
|
@ -0,0 +1,163 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Models.Search;
|
||||
using Ombi.TheMovieDbApi.Models;
|
||||
|
||||
namespace Ombi.Core
|
||||
{
|
||||
public class MovieEngine : IMovieEngine
|
||||
{
|
||||
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> ProcessMovieSearch(string search)
|
||||
{
|
||||
var api = new TheMovieDbApi.TheMovieDbApi();
|
||||
var result = await api.SearchMovie(search);
|
||||
if (result != null)
|
||||
{
|
||||
return await TransformMovieResultsToResponse(result.results);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> PopularMovies()
|
||||
{
|
||||
var api = new TheMovieDbApi.TheMovieDbApi();
|
||||
var result = await api.PopularMovies();
|
||||
if (result != null)
|
||||
{
|
||||
return await TransformMovieResultsToResponse(result.results);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> TopRatedMovies()
|
||||
{
|
||||
var api = new TheMovieDbApi.TheMovieDbApi();
|
||||
var result = await api.TopRated();
|
||||
if (result != null)
|
||||
{
|
||||
return await TransformMovieResultsToResponse(result.results);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> UpcomingMovies()
|
||||
{
|
||||
var api = new TheMovieDbApi.TheMovieDbApi();
|
||||
var result = await api.Upcoming();
|
||||
if (result != null)
|
||||
{
|
||||
return await TransformMovieResultsToResponse(result.results);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> NowPlayingMovies()
|
||||
{
|
||||
var api = new TheMovieDbApi.TheMovieDbApi();
|
||||
var result = await api.NowPlaying();
|
||||
if (result != null)
|
||||
{
|
||||
return await TransformMovieResultsToResponse(result.results);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private async Task<List<SearchMovieViewModel>> TransformMovieResultsToResponse(IEnumerable<SearchResult> movies)
|
||||
{
|
||||
await Task.Yield();
|
||||
var viewMovies = new List<SearchMovieViewModel>();
|
||||
var counter = 0;
|
||||
//Dictionary<int, RequestedModel> dbMovies = await RequestedMovies();
|
||||
foreach (var movie in movies)
|
||||
{
|
||||
var viewMovie = new SearchMovieViewModel
|
||||
{
|
||||
Adult = movie.adult,
|
||||
BackdropPath = movie.backdrop_path,
|
||||
Id = movie.id,
|
||||
OriginalLanguage = movie.original_language,
|
||||
OriginalTitle = movie.original_title,
|
||||
Overview = movie.overview,
|
||||
Popularity = movie.popularity,
|
||||
PosterPath = movie.poster_path,
|
||||
ReleaseDate = string.IsNullOrEmpty(movie.release_date) ? DateTime.MinValue : DateTime.Parse(movie.release_date),
|
||||
Title = movie.title,
|
||||
Video = movie.video,
|
||||
VoteAverage = movie.vote_average,
|
||||
VoteCount = movie.vote_count
|
||||
};
|
||||
viewMovies.Add(viewMovie);
|
||||
|
||||
//if (counter <= 5) // Let's only do it for the first 5 items
|
||||
//{
|
||||
// var movieInfo = MovieApi.GetMovieInformationWithVideos(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);
|
||||
|
||||
// var plexSettings = await PlexService.GetSettingsAsync();
|
||||
// var embySettings = await EmbySettings.GetSettingsAsync();
|
||||
// if (plexSettings.Enable)
|
||||
// {
|
||||
// var content = PlexContentRepository.GetAll();
|
||||
// var plexMovies = PlexChecker.GetPlexMovies(content);
|
||||
|
||||
// var plexMovie = PlexChecker.GetMovie(plexMovies.ToArray(), movie.Title,
|
||||
// movie.ReleaseDate?.Year.ToString(),
|
||||
// viewMovie.ImdbId);
|
||||
// if (plexMovie != null)
|
||||
// {
|
||||
// viewMovie.Available = true;
|
||||
// viewMovie.PlexUrl = plexMovie.Url;
|
||||
// }
|
||||
// }
|
||||
// if (embySettings.Enable)
|
||||
// {
|
||||
// var embyContent = EmbyContentRepository.GetAll();
|
||||
// var embyMovies = EmbyChecker.GetEmbyMovies(embyContent);
|
||||
|
||||
// var embyMovie = EmbyChecker.GetMovie(embyMovies.ToArray(), movie.Title,
|
||||
// movie.ReleaseDate?.Year.ToString(), viewMovie.ImdbId);
|
||||
// if (embyMovie != null)
|
||||
// {
|
||||
// viewMovie.Available = true;
|
||||
// }
|
||||
// }
|
||||
// if (dbMovies.ContainsKey(movie.Id) && canSee) // compare to the requests db
|
||||
// {
|
||||
// var dbm = dbMovies[movie.Id];
|
||||
|
||||
// viewMovie.Requested = true;
|
||||
// viewMovie.Approved = dbm.Approved;
|
||||
// viewMovie.Available = dbm.Available;
|
||||
// }
|
||||
// else if (canSee)
|
||||
// {
|
||||
// bool exists = IsMovieInCache(movie, viewMovie.ImdbId);
|
||||
// viewMovie.Approved = exists;
|
||||
// viewMovie.Requested = exists;
|
||||
// }
|
||||
// viewMovies.Add(viewMovie);
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
return viewMovies;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Ombi.Core
|
||||
{
|
||||
public class MovieProcessor
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard1.4</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.TheMovieDbApi.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -13,7 +13,7 @@ namespace Ombi.TheMovieDbApi
|
|||
Api = new Api.Api();
|
||||
}
|
||||
private const string ApiToken = "b8eabaf5608b88d0298aa189dd90bf00";
|
||||
private static readonly Uri BaseUri = new Uri("https://api.themoviedb.org/3/");
|
||||
private static readonly Uri BaseUri = new Uri("http://api.themoviedb.org/3/");
|
||||
public Api.Api Api { get; }
|
||||
|
||||
public async Task<MovieResponse> GetMovieInformation(int movieId)
|
||||
|
@ -31,6 +31,34 @@ namespace Ombi.TheMovieDbApi
|
|||
return await Api.Get<TheMovieDbContainer<SearchResult>>(url);
|
||||
}
|
||||
|
||||
public async Task<TheMovieDbContainer<SearchResult>> PopularMovies()
|
||||
{
|
||||
var url = BaseUri.ChangePath("movie/popular");
|
||||
url = AddHeaders(url);
|
||||
return await Api.Get<TheMovieDbContainer<SearchResult>>(url);
|
||||
}
|
||||
|
||||
public async Task<TheMovieDbContainer<SearchResult>> TopRated()
|
||||
{
|
||||
var url = BaseUri.ChangePath("movie/top_rated");
|
||||
url = AddHeaders(url);
|
||||
return await Api.Get<TheMovieDbContainer<SearchResult>>(url);
|
||||
}
|
||||
|
||||
public async Task<TheMovieDbContainer<SearchResult>> Upcoming()
|
||||
{
|
||||
var url = BaseUri.ChangePath("movie/upcoming");
|
||||
url = AddHeaders(url);
|
||||
return await Api.Get<TheMovieDbContainer<SearchResult>>(url);
|
||||
}
|
||||
|
||||
public async Task<TheMovieDbContainer<SearchResult>> NowPlaying()
|
||||
{
|
||||
var url = BaseUri.ChangePath("movie/now_playing");
|
||||
url = AddHeaders(url);
|
||||
return await Api.Get<TheMovieDbContainer<SearchResult>>(url);
|
||||
}
|
||||
|
||||
private Uri AddHeaders(Uri url)
|
||||
{
|
||||
return url.AddQueryParameter("api_key", ApiToken);
|
||||
|
|
|
@ -3,20 +3,48 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Ombi.TheMovieDbApi.Models;
|
||||
using Ombi.Core;
|
||||
using Ombi.Core.Models.Search;
|
||||
|
||||
namespace Ombi.Controllers
|
||||
{
|
||||
public class SearchController : BaseApiController
|
||||
{
|
||||
[HttpGet("movie/{searchTerm}")]
|
||||
public async Task<List<SearchResult>> SearchMovie(string searchTerm)
|
||||
public SearchController(IMovieEngine movie)
|
||||
{
|
||||
var api = new TheMovieDbApi.TheMovieDbApi();
|
||||
var result = await api.SearchMovie(searchTerm);
|
||||
return result.results;
|
||||
MovieEngine = movie;
|
||||
}
|
||||
|
||||
|
||||
private IMovieEngine MovieEngine { get; }
|
||||
|
||||
[HttpGet("movie/{searchTerm}")]
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> SearchMovie(string searchTerm)
|
||||
{
|
||||
return await MovieEngine.ProcessMovieSearch(searchTerm);
|
||||
}
|
||||
|
||||
[HttpGet("movie/popular")]
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> Popular()
|
||||
{
|
||||
return await MovieEngine.PopularMovies();
|
||||
}
|
||||
[HttpGet("movie/nowplaying")]
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> NowPlayingMovies()
|
||||
{
|
||||
return await MovieEngine.NowPlayingMovies();
|
||||
}
|
||||
[HttpGet("movie/toprated")]
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> TopRatedMovies()
|
||||
{
|
||||
return await MovieEngine.TopRatedMovies();
|
||||
}
|
||||
[HttpGet("movie/upcoming")]
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> UpcomingMovies()
|
||||
{
|
||||
return await MovieEngine.UpcomingMovies();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,12 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="ViewModels\" />
|
||||
<Folder Include="wwwroot\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ombi.Core\Ombi.Core.csproj" />
|
||||
<ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.TheMovieDbApi.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -11,6 +11,7 @@ using Microsoft.Extensions.Configuration;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Core;
|
||||
|
||||
namespace Ombi
|
||||
{
|
||||
|
@ -33,6 +34,7 @@ namespace Ombi
|
|||
{
|
||||
// Add framework services.
|
||||
services.AddMvc();
|
||||
services.AddTransient<IMovieEngine, MovieEngine>();
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<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 [routerLink]="['/search']"><i class="fa fa-search"></i> Search</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
export interface IMovieResult {
|
||||
poster_path: string,
|
||||
adult: boolean,
|
||||
overview: string,
|
||||
release_date: string,
|
||||
genre_ids: number[],
|
||||
id: number,
|
||||
original_title: string,
|
||||
original_language: string,
|
||||
title: string,
|
||||
backdrop_path: string,
|
||||
popularity: number,
|
||||
vote_count: number,
|
||||
video: boolean,
|
||||
vote_average:number
|
||||
}
|
20
Ombi/Ombi/app/search/interfaces/ISearchMovieResult.ts
Normal file
20
Ombi/Ombi/app/search/interfaces/ISearchMovieResult.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
export interface ISearchMovieResult {
|
||||
backdropPath: string,
|
||||
adult: boolean,
|
||||
overview: string,
|
||||
releaseDate: Date,
|
||||
genreIds: number[],
|
||||
id: number,
|
||||
originalTitle: string,
|
||||
originalLanguage: string,
|
||||
title: string,
|
||||
posterPath: string,
|
||||
popularity: number,
|
||||
voteCount: number,
|
||||
video: boolean,
|
||||
voteAverage: number,
|
||||
alreadyInCp: boolean,
|
||||
trailer: string,
|
||||
homepage: string,
|
||||
imdbId:string
|
||||
}
|
|
@ -1,48 +1,50 @@
|
|||
<h1 id="searchTitle">Search</h1>
|
||||
<h1 id="searchTitle">Search</h1>
|
||||
<h4>Search Paragraph</h4>
|
||||
<br />
|
||||
<!-- Nav tabs -->
|
||||
|
||||
|
||||
<ul id="nav-tabs" class="nav nav-tabs" role="tablist">
|
||||
|
||||
|
||||
<li role="presentation" class="active">
|
||||
<a id="movieTabButton" href="#MoviesTab" aria-controls="home" role="tab" data-toggle="tab"><i class="fa fa-film"></i> Movies</a>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li role="presentation">
|
||||
<a id="actorTabButton" href="#ActorsTab" aria-controls="profile" role="tab" data-toggle="tab"><i class="fa fa-users"></i> Actors</a>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li role="presentation">
|
||||
<a id="tvTabButton" href="#TvShowTab" aria-controls="profile" role="tab" data-toggle="tab"><i class="fa fa-television"></i> TV Shows</a>
|
||||
|
||||
</li>
|
||||
<!--
|
||||
<li role="presentation">
|
||||
<a href="#MusicTab" aria-controls="profile" role="tab" data-toggle="tab"><i class="fa fa-music"></i> Albums</a>
|
||||
</li>-->
|
||||
|
||||
<!--
|
||||
<li role="presentation">
|
||||
<a href="#MusicTab" aria-controls="profile" role="tab" data-toggle="tab"><i class="fa fa-music"></i> Albums</a>
|
||||
</li>-->
|
||||
|
||||
</ul>
|
||||
|
||||
<!-- Tab panes -->
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
|
||||
<!-- Movie tab -->
|
||||
<div role="tabpanel" class="tab-pane active" id="MoviesTab">
|
||||
<div class="input-group">
|
||||
<input id="movieSearchContent" type="text" class="form-control form-control-custom form-control-search form-control-withbuttons" (change)="search($event)">
|
||||
<input id="movieSearchContent" type="text" class="form-control form-control-custom form-control-search form-control-withbuttons" (keyup)="search($event)">
|
||||
<div class="input-group-addon">
|
||||
<div class="btn-group">
|
||||
<a href="#" class="btn btn-sm btn-primary-outline dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
|
||||
@UI.Search_Suggestions
|
||||
Suggestions
|
||||
<i class="fa fa-chevron-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="moviesComingSoon" href="#">@UI.Search_ComingSoon</a></li>
|
||||
<li><a id="moviesInTheaters" href="#">@UI.Search_InTheaters</a></li>
|
||||
<li><a (click)="popularMovies()">Popular Movies</a></li>
|
||||
<li><a (click)="upcomingMovies()">Upcoming Movies</a></li>
|
||||
<li><a (click)="topRatedMovies()">Top Rated Movies</a></li>
|
||||
<li><a (click)="nowPlayingMovies()">Now Playing Movies</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<i id="movieSearchButton" class="fa fa-search"></i>
|
||||
|
@ -85,7 +87,7 @@
|
|||
<i class="fa fa-chevron-down"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="popularShows" href="#">Popular Shows</a></li>
|
||||
<li><a id="popularShows" >Popular Shows</a></li>
|
||||
<li><a id="trendingShows" href="#">Trending Shows</a></li>
|
||||
<li><a id="mostWatchedShows" href="#">Most Watched Shows</a></li>
|
||||
<li><a id="anticipatedShows" href="#">Most Anticipated Shows</a></li>
|
||||
|
@ -101,17 +103,146 @@
|
|||
</div>
|
||||
|
||||
<!-- Music tab -->
|
||||
<!-- <div role="tabpanel" class="tab-pane" id="MusicTab">
|
||||
<div class="input-group">
|
||||
<input id="musicSearchContent" type="text" class="form-control form-control-custom form-control-search">
|
||||
<div class="input-group-addon">
|
||||
<i id="musicSearchButton" class="fa fa-search"></i>
|
||||
<!-- <div role="tabpanel" class="tab-pane" id="MusicTab">
|
||||
<div class="input-group">
|
||||
<input id="musicSearchContent" type="text" class="form-control form-control-custom form-control-search">
|
||||
<div class="input-group-addon">
|
||||
<i id="musicSearchButton" class="fa fa-search"></i>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<div id="musicList">
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<div id="musicList">
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
-->
|
||||
|
||||
<div *ngFor="let result of movieResults">
|
||||
<div class="row">
|
||||
<div id="{{id}}imgDiv" class="col-sm-2">
|
||||
|
||||
|
||||
<img *ngIf="result.posterPath" class="img-responsive" src="https://image.tmdb.org/t/p/w150/{{result.posterPath}}" alt="poster">
|
||||
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<div>
|
||||
<a href="https://www.themoviedb.org/movie/{{result.id}}/" target="_blank">
|
||||
<h4>{{result.title}} ({{result.releaseDate}})</h4>
|
||||
</a>
|
||||
|
||||
|
||||
<span *ngIf="result.firstAired" class="label label-info" target="_blank">Air Date: {{result.firstAired}}</span>
|
||||
|
||||
|
||||
<span *ngIf="result.releaseDate" class="label label-info" target="_blank">Release Date: {{result.releaseDate}}</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>
|
||||
<template #requested>
|
||||
<span class="label label-warning">Pending Approval</span>
|
||||
</template>
|
||||
|
||||
<template #notRequested>
|
||||
<span class="label label-danger">Not Yet Requested</span>
|
||||
</template>
|
||||
|
||||
|
||||
<span id="{{id}}netflixTab"></span>
|
||||
|
||||
<a *ngIf="result.homepage" href="{{result.homepage}}" target="_blank"><span class="label label-info">HomePage</span></a>
|
||||
|
||||
<a *ngIf="result.trailer" href="{{result.trailer}}" target="_blank"><span class="label label-info">Trailer</span></a>
|
||||
|
||||
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
<p style="font-size:0.9rem !important">{{result.overview}}</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-sm-2">
|
||||
<input name="{{type}}Id" type="text" value="{{result.id}}" hidden="hidden" />
|
||||
|
||||
<div *ngIf="result.available">
|
||||
<button style="text-align: right" class="btn btn-success-outline disabled" disabled><i class="fa fa-check"></i> Available</button>
|
||||
|
||||
<div *ngIf="result.url">
|
||||
<br />
|
||||
<br />
|
||||
<a style="text-align: right" class="btn btn-sm btn-primary-outline" href="{{result.url}}" target="_blank"><i class="fa fa-eye"></i> View In Plex</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="result.requested; then requestedBtn else notRequestedBtn"></div>
|
||||
<template #requestedBtn>
|
||||
<button style="text-align: right" class="btn btn-primary-outline disabled" [disabled]><i class="fa fa-check"></i> Requested</button>
|
||||
</template>
|
||||
<template #notRequestedBtn>
|
||||
<button id="{{result.id}}" style="text-align: right" class="btn btn-primary-outline" (click)="request(result)"><i class="fa fa-plus"></i> Request</button>
|
||||
</template>
|
||||
|
||||
<!--{{#if_eq type "tv"}}
|
||||
{{#if_eq tvFullyAvailable true}}
|
||||
@*//TODO Not used yet*@
|
||||
<button style="text-align: right" class="btn btn-success-outline disabled" disabled><i class="fa fa-check"></i> @UI.Search_Available</button><br />
|
||||
{{else}}
|
||||
{{#if_eq enableTvRequestsForOnlySeries true}}
|
||||
<button id="{{id}}" style="text-align: right" class="btn {{#if available}}btn-success-outline{{else}}btn-primary-outline dropdownTv{{/if}} btn-primary-outline" season-select="0" type="button" {{#if available}} disabled{{/if}}><i class="fa fa-plus"></i> {{#if available}}@UI.Search_Available{{else}}@UI.Search_Request{{/if}}</button>
|
||||
{{else}}
|
||||
<div class="dropdown">
|
||||
<button id="{{id}}" class="btn {{#if available}}btn-success-outline{{else}}btn-primary-outline{{/if}} dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<i class="fa fa-plus"></i> {{#if available}}@UI.Search_Available{{else}}@UI.Search_Request {{/if}}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li><a id="{{id}}" season-select="0" class="dropdownTv " href="#">@UI.Search_AllSeasons</a></li>
|
||||
{{#if_eq disableTvRequestsBySeason false}}
|
||||
<li><a id="{{id}}" season-select="1" class="dropdownTv" href="#">@UI.Search_FirstSeason</a></li>
|
||||
<li><a id="{{id}}" season-select="2" class="dropdownTv" href="#">@UI.Search_LatestSeason</a></li>
|
||||
<li><a id="SeasonSelect" data-identifier="{{id}}" data-toggle="modal" data-target="#seasonsModal" href="#">@UI.Search_SelectSeason...</a></li>
|
||||
{{/if_eq}}
|
||||
{{#if_eq disableTvRequestsByEpisode false}}
|
||||
<li><a id="EpisodeSelect" data-identifier="{{id}}" data-toggle="modal" data-target="#episodesModal" href="#">@UI.Search_SelectEpisode...</a></li>
|
||||
{{/if_eq}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if_eq}}
|
||||
{{#if available}}
|
||||
{{#if url}}
|
||||
<br />
|
||||
<a style="text-align: right" class="btn btn-sm btn-primary-outline" href="{{url}}" target="_blank"><i class="fa fa-eye"></i> @UI.Search_ViewInPlex</a>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if_eq}}
|
||||
{{/if_eq}}-->
|
||||
|
||||
|
||||
<br />
|
||||
<div *ngIf="result.available">
|
||||
<input name="providerId" type="text" value="{{id}}" hidden="hidden" />
|
||||
<input name="type" type="text" value="{{type}}" hidden="hidden" />
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-sm btn-danger-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<i class="fa fa-exclamation"></i> @UI.Search_ReportIssue
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li><a issue-select="0" class="dropdownIssue" href="#">@UI.Issues_WrongAudio</a></li>
|
||||
<li><a issue-select="1" class="dropdownIssue" href="#">@UI.Issues_NoSubs</a></li>
|
||||
<li><a issue-select="2" class="dropdownIssue" href="#">@UI.Issues_WrongContent</a></li>
|
||||
<li><a issue-select="3" class="dropdownIssue" href="#">@UI.Issues_Playback</a></li>
|
||||
<li><a issue-select="4" class="dropdownIssue" href="#" data-toggle="modal" data-target="#issuesModal">@UI.Issues_Other</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<hr />
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@ import 'rxjs/add/operator/map';
|
|||
|
||||
import { SearchService } from '../services/search.service';
|
||||
|
||||
import { IMovieResult } from './interfaces/IMovieResult';
|
||||
import { ISearchMovieResult } from './interfaces/ISearchMovieResult';
|
||||
|
||||
@Component({
|
||||
selector: 'ombi',
|
||||
|
@ -18,16 +18,20 @@ export class SearchComponent implements OnInit {
|
|||
|
||||
searchText: string;
|
||||
searchChanged: Subject<string> = new Subject<string>();
|
||||
movieResults: IMovieResult[];
|
||||
movieResults: ISearchMovieResult[];
|
||||
|
||||
constructor(private searchService: SearchService) {
|
||||
//this.searchChanged
|
||||
// .debounceTime(300) // wait 300ms after the last event before emitting last event
|
||||
// .distinctUntilChanged() // only emit if value is different from previous value
|
||||
// .subscribe(x => {
|
||||
// this.searchText = x as string;
|
||||
//
|
||||
// });
|
||||
this.searchChanged
|
||||
.debounceTime(600) // Wait Xms afterthe last event before emitting last event
|
||||
.distinctUntilChanged() // only emit if value is different from previous value
|
||||
.subscribe(x => {
|
||||
this.searchText = x as string;
|
||||
if (this.searchText === "") {
|
||||
this.clearResults();
|
||||
return;
|
||||
}
|
||||
this.searchService.searchMovie(this.searchText).subscribe(x => this.movieResults = x);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
@ -36,8 +40,32 @@ export class SearchComponent implements OnInit {
|
|||
}
|
||||
|
||||
search(text: any) {
|
||||
//this.searchChanged.next(text);
|
||||
this.searchService.searchMovie(text.target.value).subscribe(x => this.movieResults = x);
|
||||
this.searchChanged.next(text.target.value);
|
||||
}
|
||||
|
||||
request(searchResult: ISearchMovieResult) {
|
||||
console.log(searchResult);
|
||||
}
|
||||
|
||||
popularMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.popularMovies().subscribe(x => this.movieResults = x);
|
||||
}
|
||||
nowPlayingMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.nowPlayingMovies().subscribe(x => this.movieResults = x);
|
||||
}
|
||||
topRatedMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.topRatedMovies().subscribe(x => this.movieResults = x);
|
||||
}
|
||||
upcomingMovies() {
|
||||
this.clearResults();
|
||||
this.searchService.upcomignMovies().subscribe(x => this.movieResults = x);
|
||||
}
|
||||
|
||||
private clearResults() {
|
||||
this.movieResults = [];
|
||||
}
|
||||
|
||||
}
|
|
@ -3,14 +3,27 @@ import { Http } from '@angular/http';
|
|||
import { Observable } from 'rxjs/Rx';
|
||||
|
||||
import { ServiceHelpers } from './service.helpers';
|
||||
import { IMovieResult } from '../search/interfaces/IMovieResult';
|
||||
import { ISearchMovieResult } from '../search/interfaces/ISearchMovieResult';
|
||||
|
||||
@Injectable()
|
||||
export class SearchService {
|
||||
constructor(private http: Http) {
|
||||
}
|
||||
|
||||
searchMovie(searchTerm: string): Observable<IMovieResult[]> {
|
||||
searchMovie(searchTerm: string): Observable<ISearchMovieResult[]> {
|
||||
return this.http.get('/api/Search/Movie/' + searchTerm).map(ServiceHelpers.extractData);
|
||||
}
|
||||
|
||||
popularMovies(): Observable<ISearchMovieResult[]> {
|
||||
return this.http.get('/api/Search/Movie/Popular').map(ServiceHelpers.extractData);
|
||||
}
|
||||
upcomignMovies(): Observable<ISearchMovieResult[]> {
|
||||
return this.http.get('/api/Search/Movie/upcoming').map(ServiceHelpers.extractData);
|
||||
}
|
||||
nowPlayingMovies(): Observable<ISearchMovieResult[]> {
|
||||
return this.http.get('/api/Search/Movie/nowplaying').map(ServiceHelpers.extractData);
|
||||
}
|
||||
topRatedMovies(): Observable<ISearchMovieResult[]> {
|
||||
return this.http.get('/api/Search/Movie/toprated').map(ServiceHelpers.extractData);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue