mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-14 02:26:55 -07:00
MORE!
This commit is contained in:
parent
4118f0de41
commit
6ee9606f7c
23 changed files with 314 additions and 29 deletions
|
@ -29,5 +29,6 @@ namespace Ombi.Core.Engine.Interfaces
|
|||
Task<IEnumerable<StreamingData>> GetStreamInformation(int movieDbId, CancellationToken cancellationToken);
|
||||
Task<IEnumerable<SearchMovieViewModel>> RecentlyRequestedMovies(int currentlyLoaded, int toLoad, CancellationToken cancellationToken);
|
||||
Task<IEnumerable<SearchMovieViewModel>> SeasonalList(int currentPosition, int amountToLoad, CancellationToken cancellationToken);
|
||||
Task<IEnumerable<SearchMovieViewModel>> AdvancedSearch(DiscoverModel model, int currentlyLoaded, int toLoad, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
|
@ -137,7 +137,22 @@ namespace Ombi.Core.Engine.V2
|
|||
foreach (var pagesToLoad in pages)
|
||||
{
|
||||
var apiResult = await Cache.GetOrAddAsync(nameof(PopularMovies) + pagesToLoad.Page + langCode,
|
||||
() => MovieApi.PopularMovies(langCode, pagesToLoad.Page, cancellationToken), DateTimeOffset.Now.AddHours(12));
|
||||
() => MovieApi.PopularMovies(langCode, pagesToLoad.Page, cancellationToken), DateTimeOffset.Now.AddHours(12));
|
||||
results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take));
|
||||
}
|
||||
return await TransformMovieResultsToResponse(results);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SearchMovieViewModel>> AdvancedSearch(DiscoverModel model, int currentlyLoaded, int toLoad, CancellationToken cancellationToken)
|
||||
{
|
||||
var langCode = await DefaultLanguageCode(null);
|
||||
|
||||
var pages = PaginationHelper.GetNextPages(currentlyLoaded, toLoad, _theMovieDbMaxPageItems);
|
||||
|
||||
var results = new List<MovieDbSearchResult>();
|
||||
foreach (var pagesToLoad in pages)
|
||||
{
|
||||
var apiResult = await MovieApi.AdvancedSearch(model, cancellationToken);
|
||||
results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take));
|
||||
}
|
||||
return await TransformMovieResultsToResponse(results);
|
||||
|
|
|
@ -40,5 +40,7 @@ namespace Ombi.Api.TheMovieDb
|
|||
Task<WatchProviders> GetMovieWatchProviders(int theMoviedbId, CancellationToken token);
|
||||
Task<WatchProviders> GetTvWatchProviders(int theMoviedbId, CancellationToken token);
|
||||
Task<List<Genre>> GetGenres(string media, CancellationToken cancellationToken);
|
||||
Task<List<WatchProvidersResults>> SearchWatchProviders(string media, string searchTerm, CancellationToken cancellationToken);
|
||||
Task<List<MovieDbSearchResult>> AdvancedSearch(DiscoverModel model, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
18
src/Ombi.TheMovieDbApi/Models/DiscoverModel.cs
Normal file
18
src/Ombi.TheMovieDbApi/Models/DiscoverModel.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ombi.Api.TheMovieDb.Models
|
||||
{
|
||||
public class DiscoverModel
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public int? ReleaseYear { get; set; }
|
||||
public List<int> GenreIds { get; set; } = new List<int>();
|
||||
public List<int> KeywordIds { get; set; } = new List<int>();
|
||||
public List<int> WatchProviders { get; set; } = new List<int>();
|
||||
public List<int> Companies { get; set; } = new List<int>();
|
||||
}
|
||||
}
|
21
src/Ombi.TheMovieDbApi/Models/DiscoverTv.cs
Normal file
21
src/Ombi.TheMovieDbApi/Models/DiscoverTv.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
namespace Ombi.Api.TheMovieDb.Models {
|
||||
|
||||
public class DiscoverTv
|
||||
{
|
||||
public int vote_count { get; set; }
|
||||
public int id { get; set; }
|
||||
public bool video { get; set; }
|
||||
public float vote_average { get; set; }
|
||||
public string title { get; set; }
|
||||
public float popularity { get; set; }
|
||||
public string poster_path { get; set; }
|
||||
public string original_language { get; set; }
|
||||
public string original_title { get; set; }
|
||||
public int[] genre_ids { get; set; }
|
||||
public string backdrop_path { get; set; }
|
||||
public bool adult { get; set; }
|
||||
public string overview { get; set; }
|
||||
public string release_date { get; set; }
|
||||
}
|
||||
|
||||
}
|
16
src/Ombi.TheMovieDbApi/Models/WatchProvidersResults.cs
Normal file
16
src/Ombi.TheMovieDbApi/Models/WatchProvidersResults.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ombi.Api.TheMovieDb.Models
|
||||
{
|
||||
public class WatchProvidersResults
|
||||
{
|
||||
public int provider_id { get; set; }
|
||||
public string logo_path { get; set; }
|
||||
public string provider_name { get; set; }
|
||||
public string origin_country { get; set; }
|
||||
}
|
||||
}
|
|
@ -68,6 +68,34 @@ namespace Ombi.Api.TheMovieDb
|
|||
return await Api.Request<TheMovieDbContainer<DiscoverMovies>>(request);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task<List<MovieDbSearchResult>> AdvancedSearch(DiscoverModel model, CancellationToken cancellationToken)
|
||||
{
|
||||
var request = new Request($"discover/{model.Type}", BaseUri, HttpMethod.Get);
|
||||
request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken);
|
||||
if(model.ReleaseYear.HasValue && model.ReleaseYear.Value > 1900)
|
||||
{
|
||||
request.FullUri = request.FullUri.AddQueryParameter("year", model.ReleaseYear.Value.ToString());
|
||||
}
|
||||
if (model.KeywordIds.Any())
|
||||
{
|
||||
request.FullUri = request.FullUri.AddQueryParameter("with_keyword", string.Join(',', model.KeywordIds));
|
||||
}
|
||||
if (model.GenreIds.Any())
|
||||
{
|
||||
request.FullUri = request.FullUri.AddQueryParameter("with_genres", string.Join(',', model.GenreIds));
|
||||
}
|
||||
if (model.WatchProviders.Any())
|
||||
{
|
||||
request.FullUri = request.FullUri.AddQueryParameter("with_watch_providers", string.Join(',', model.WatchProviders));
|
||||
}
|
||||
request.FullUri = request.FullUri.AddQueryParameter("sort_by", "popularity.desc");
|
||||
|
||||
var result = await Api.Request<TheMovieDbContainer<SearchResult>>(request, cancellationToken);
|
||||
return Mapper.Map<List<MovieDbSearchResult>>(result.results);
|
||||
}
|
||||
|
||||
public async Task<Collections> GetCollection(string langCode, int collectionId, CancellationToken cancellationToken)
|
||||
{
|
||||
// https://developers.themoviedb.org/3/discover/movie-discover
|
||||
|
@ -368,6 +396,17 @@ namespace Ombi.Api.TheMovieDb
|
|||
return result.results ?? new List<TheMovidDbKeyValue>();
|
||||
}
|
||||
|
||||
public async Task<List<WatchProvidersResults>> SearchWatchProviders(string media, string searchTerm, CancellationToken cancellationToken)
|
||||
{
|
||||
var request = new Request($"/watch/providers/{media}", BaseUri, HttpMethod.Get);
|
||||
request.AddQueryString("api_key", ApiToken);
|
||||
request.AddQueryString("query", searchTerm);
|
||||
AddRetry(request);
|
||||
|
||||
var result = await Api.Request<TheMovieDbContainer<WatchProvidersResults>>(request, cancellationToken);
|
||||
return result.results ?? new List<WatchProvidersResults>();
|
||||
}
|
||||
|
||||
public async Task<TheMovidDbKeyValue> GetKeyword(int keywordId)
|
||||
{
|
||||
var request = new Request($"keyword/{keywordId}", BaseUri, HttpMethod.Get);
|
||||
|
|
|
@ -2,3 +2,18 @@
|
|||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface IWatchProvidersResults {
|
||||
provider_id: number;
|
||||
logo_path: string;
|
||||
provider_name: string;
|
||||
}
|
||||
|
||||
export interface IDiscoverModel {
|
||||
type: string;
|
||||
releaseYear?: number|undefined;
|
||||
genreIds?: number[];
|
||||
keywordIds?: number[];
|
||||
watchProviders?: number[];
|
||||
companies?: number[];
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
<mat-slide-toggle id="filterMusic" class="mat-menu-item slide-menu" [checked]="searchFilter.music"
|
||||
(click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.Music)">
|
||||
{{ 'NavigationBar.Filter.Music' | translate}}</mat-slide-toggle>
|
||||
<button (click)="openAdvancedSearch()">Advanced Search</button>
|
||||
<button class="advanced-search" mat-raised-button color="accent" (click)="openAdvancedSearch()">Advanced Search</button>
|
||||
<!-- <mat-slide-toggle class="mat-menu-item slide-menu" [checked]="searchFilter.people"
|
||||
(click)="$event.stopPropagation()" (change)="changeFilter($event,SearchFilterType.People)">
|
||||
{{ 'NavigationBar.Filter.People' | translate}}</mat-slide-toggle> -->
|
||||
|
|
|
@ -230,4 +230,8 @@
|
|||
::ng-deep .mat-sidenav-fixed .mat-list-base .mat-list-item .mat-list-item-content, .mat-list-base .mat-list-option .mat-list-item-content{
|
||||
padding:0;
|
||||
margin: 0 4em 0 0.5em;
|
||||
}
|
||||
|
||||
.advanced-search {
|
||||
margin-left: 10px;
|
||||
}
|
|
@ -4,7 +4,7 @@ import { Injectable, Inject } from "@angular/core";
|
|||
import { empty, Observable, throwError } from "rxjs";
|
||||
import { catchError } from "rxjs/operators";
|
||||
|
||||
import { IMovieDbKeyword } from "../../interfaces";
|
||||
import { IMovieDbKeyword, IWatchProvidersResults } from "../../interfaces";
|
||||
import { ServiceHelpers } from "../service.helpers";
|
||||
|
||||
@Injectable({
|
||||
|
@ -28,4 +28,8 @@ export class TheMovieDbService extends ServiceHelpers {
|
|||
public getGenres(media: string): Observable<IMovieDbKeyword[]> {
|
||||
return this.http.get<IMovieDbKeyword[]>(`${this.url}/Genres/${media}`, { headers: this.headers })
|
||||
}
|
||||
|
||||
public getWatchProviders(media: string): Observable<IWatchProvidersResults[]> {
|
||||
return this.http.get<IWatchProvidersResults[]>(`${this.url}/WatchProviders/${media}`, {headers: this.headers});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Injectable, Inject } from "@angular/core";
|
|||
import { HttpClient } from "@angular/common/http";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { IMultiSearchResult, ISearchMovieResult, ISearchTvResult } from "../interfaces";
|
||||
import { IDiscoverModel, IMultiSearchResult, ISearchMovieResult, ISearchTvResult } from "../interfaces";
|
||||
import { ServiceHelpers } from "./service.helpers";
|
||||
|
||||
import { ISearchMovieResultV2 } from "../interfaces/ISearchMovieResultV2";
|
||||
|
@ -51,6 +51,10 @@ export class SearchV2Service extends ServiceHelpers {
|
|||
return this.http.get<ISearchMovieResult[]>(`${this.url}/Movie/Popular/${currentlyLoaded}/${toLoad}`).toPromise();
|
||||
}
|
||||
|
||||
public advancedSearch(model: IDiscoverModel, currentlyLoaded: number, toLoad: number): Promise<ISearchMovieResult[]> {
|
||||
return this.http.post<ISearchMovieResult[]>(`${this.url}/advancedSearch/Movie/${currentlyLoaded}/${toLoad}`, model).toPromise();
|
||||
}
|
||||
|
||||
public upcomingMovies(): Observable<ISearchMovieResult[]> {
|
||||
return this.http.get<ISearchMovieResult[]>(`${this.url}/Movie/upcoming`);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<form [formGroup]="form" *ngIf="form">
|
||||
<form [formGroup]="form" (ngSubmit)="onSubmit()" *ngIf="form">
|
||||
<h1 id="advancedOptionsTitle">
|
||||
<i class="fas fa-sliders-h"></i> Advanced Search
|
||||
</h1>
|
||||
|
@ -34,6 +34,10 @@
|
|||
<div class="col-md-6">
|
||||
<genre-select [form]="form" [mediaType]="form.controls.type.value"></genre-select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<watch-providers-select [form]="form" [mediaType]="form.controls.type.value"></watch-providers-select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -49,10 +53,10 @@
|
|||
<button
|
||||
mat-raised-button
|
||||
id="requestButton"
|
||||
(click)="submitRequest()"
|
||||
color="accent"
|
||||
type="submit"
|
||||
>
|
||||
<i class="fas fa-plus"></i> {{ "Common.Request" | translate }}
|
||||
<i class="fas fa-plus"></i> {{ "Common.Search" | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { Component, Inject, OnInit } from "@angular/core";
|
||||
import { FormBuilder, FormGroup } from "@angular/forms";
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog";
|
||||
import { IDiscoverModel } from "../../interfaces";
|
||||
import { SearchV2Service } from "../../services";
|
||||
|
||||
|
||||
@Component({
|
||||
|
@ -12,7 +14,8 @@ export class AdvancedSearchDialogComponent implements OnInit {
|
|||
constructor(
|
||||
public dialogRef: MatDialogRef<AdvancedSearchDialogComponent, string>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
private fb: FormBuilder
|
||||
private fb: FormBuilder,
|
||||
private searchService: SearchV2Service,
|
||||
) {}
|
||||
|
||||
public form: FormGroup;
|
||||
|
@ -21,16 +24,28 @@ export class AdvancedSearchDialogComponent implements OnInit {
|
|||
public async ngOnInit() {
|
||||
|
||||
this.form = this.fb.group({
|
||||
keywords: [[]],
|
||||
genres: [[]],
|
||||
keywordIds: [[]],
|
||||
genreIds: [[]],
|
||||
releaseYear: [],
|
||||
type: ['movie'],
|
||||
watchProviders: [[]],
|
||||
})
|
||||
|
||||
this.form.controls.type.valueChanges.subscribe(val => {
|
||||
this.form.controls.genres.setValue([]);
|
||||
this.form.controls.watchProviders.setValue([]);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
public async onSubmit() {
|
||||
const watchProviderIds = <number[]>this.form.controls.watchProviders.value.map(x => x.provider_id);
|
||||
const genres = <number[]>this.form.controls.genreIds.value.map(x => x.id);
|
||||
await this.searchService.advancedSearch({
|
||||
watchProviders: watchProviderIds,
|
||||
genreIds: genres,
|
||||
type: this.form.controls.type.value,
|
||||
}, 0, 30);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<mat-label>Genres</mat-label>
|
||||
<mat-chip-list #chipList aria-label="Fruit selection">
|
||||
<mat-chip
|
||||
*ngFor="let word of form.controls.genres.value"
|
||||
*ngFor="let word of form.controls.genreIds.value"
|
||||
[removable]="true"
|
||||
(removed)="remove(word)">
|
||||
{{word.name}}
|
||||
|
|
|
@ -11,7 +11,7 @@ import { TheMovieDbService } from "../../../services";
|
|||
selector: "genre-select",
|
||||
templateUrl: "genre-select.component.html"
|
||||
})
|
||||
export class GenreSelectComponent implements OnInit {
|
||||
export class GenreSelectComponent {
|
||||
constructor(
|
||||
private tmdbService: TheMovieDbService
|
||||
) {}
|
||||
|
@ -39,32 +39,24 @@ export class GenreSelectComponent implements OnInit {
|
|||
|
||||
@ViewChild('keywordInput') input: ElementRef<HTMLInputElement>;
|
||||
|
||||
async ngOnInit() {
|
||||
|
||||
// this.genres = await this.tmdbService.getGenres(this.mediaType).toPromise();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
remove(word: IMovieDbKeyword): void {
|
||||
const exisiting = this.form.controls.genres.value;
|
||||
const exisiting = this.form.controls.genreIds.value;
|
||||
const index = exisiting.indexOf(word);
|
||||
|
||||
if (index >= 0) {
|
||||
exisiting.splice(index, 1);
|
||||
this.form.controls.genres.setValue(exisiting);
|
||||
this.form.controls.genreIds.setValue(exisiting);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
selected(event: MatAutocompleteSelectedEvent): void {
|
||||
const val = event.option.value;
|
||||
const exisiting = this.form.controls.genres.value;
|
||||
const exisiting = this.form.controls.genreIds.value;
|
||||
if(exisiting.indexOf(val) < 0) {
|
||||
exisiting.push(val);
|
||||
}
|
||||
this.form.controls.genres.setValue(exisiting);
|
||||
this.form.controls.genreIds.setValue(exisiting);
|
||||
this.input.nativeElement.value = '';
|
||||
this.control.setValue(null);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<mat-label>Keywords</mat-label>
|
||||
<mat-chip-list #chipList aria-label="Fruit selection">
|
||||
<mat-chip
|
||||
*ngFor="let word of form.controls.keywords.value"
|
||||
*ngFor="let word of form.controls.keywordIds.value"
|
||||
[removable]="true"
|
||||
(removed)="remove(word)">
|
||||
{{word.name}}
|
||||
|
|
|
@ -40,23 +40,23 @@ export class KeywordSearchComponent implements OnInit {
|
|||
};
|
||||
|
||||
remove(word: IMovieDbKeyword): void {
|
||||
const exisiting = this.form.controls.keywords.value;
|
||||
const exisiting = this.form.controls.keywordIds.value;
|
||||
const index = exisiting.indexOf(word);
|
||||
|
||||
if (index >= 0) {
|
||||
exisiting.splice(index, 1);
|
||||
this.form.controls.keywords.setValue(exisiting);
|
||||
this.form.controls.keywordIds.setValue(exisiting);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
selected(event: MatAutocompleteSelectedEvent): void {
|
||||
const val = event.option.value;
|
||||
const exisiting = this.form.controls.keywords.value;
|
||||
const exisiting = this.form.controls.keywordIds.value;
|
||||
if (exisiting.indexOf(val) < 0) {
|
||||
exisiting.push(val);
|
||||
}
|
||||
this.form.controls.keywords.setValue(exisiting);
|
||||
this.form.controls.keywordIds.setValue(exisiting);
|
||||
this.input.nativeElement.value = '';
|
||||
this.control.setValue(null);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<mat-form-field class="example-chip-list" appearance="fill">
|
||||
<mat-label>Watch Providers</mat-label>
|
||||
<mat-chip-list #chipList aria-label="Fruit selection">
|
||||
<mat-chip
|
||||
*ngFor="let word of form.controls.watchProviders.value"
|
||||
[removable]="true"
|
||||
(removed)="remove(word)">
|
||||
{{word.provider_name}}
|
||||
<mat-icon matChipRemove>cancel</mat-icon>
|
||||
</mat-chip>
|
||||
<input
|
||||
placeholder="Search Keyword"
|
||||
#keywordInput
|
||||
[formControl]="control"
|
||||
[matAutocomplete]="auto"
|
||||
[matChipInputFor]="chipList"/>
|
||||
</mat-chip-list>
|
||||
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
|
||||
<mat-option *ngFor="let word of filteredList | async" [value]="word">
|
||||
{{word.provider_name}}
|
||||
</mat-option>
|
||||
</mat-autocomplete>
|
||||
</mat-form-field>
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
import { Component, ElementRef, Input, OnInit, ViewChild } from "@angular/core";
|
||||
import { FormControl, FormGroup } from "@angular/forms";
|
||||
import { IMovieDbKeyword, IWatchProvidersResults } from "../../../interfaces";
|
||||
import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from "rxjs/operators";
|
||||
|
||||
import { MatAutocompleteSelectedEvent } from "@angular/material/autocomplete";
|
||||
import { Observable } from "rxjs";
|
||||
import { TheMovieDbService } from "../../../services";
|
||||
|
||||
@Component({
|
||||
selector: "watch-providers-select",
|
||||
templateUrl: "watch-providers-select.component.html"
|
||||
})
|
||||
export class WatchProvidersSelectComponent {
|
||||
constructor(
|
||||
private tmdbService: TheMovieDbService
|
||||
) {}
|
||||
|
||||
private _mediaType: string;
|
||||
@Input() set mediaType(type: string) {
|
||||
this._mediaType = type;
|
||||
this.tmdbService.getWatchProviders(this._mediaType).subscribe((res) => {
|
||||
this.watchProviders = res;
|
||||
this.filteredList = this.control.valueChanges.pipe(
|
||||
startWith(''),
|
||||
map((genre: string | null) => genre ? this._filter(genre) : this.watchProviders.slice()));
|
||||
});
|
||||
|
||||
}
|
||||
get mediaType(): string {
|
||||
return this._mediaType;
|
||||
}
|
||||
@Input() public form: FormGroup;
|
||||
|
||||
public watchProviders: IWatchProvidersResults[] = [];
|
||||
public control = new FormControl();
|
||||
public filteredTags: IWatchProvidersResults[];
|
||||
public filteredList: Observable<IWatchProvidersResults[]>;
|
||||
|
||||
@ViewChild('keywordInput') input: ElementRef<HTMLInputElement>;
|
||||
|
||||
|
||||
remove(word: IWatchProvidersResults): void {
|
||||
const exisiting = this.form.controls.watchProviders.value;
|
||||
const index = exisiting.indexOf(word);
|
||||
|
||||
if (index >= 0) {
|
||||
exisiting.splice(index, 1);
|
||||
this.form.controls.watchProviders.setValue(exisiting);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
selected(event: MatAutocompleteSelectedEvent): void {
|
||||
const val = event.option.value;
|
||||
const exisiting = this.form.controls.watchProviders.value;
|
||||
if (exisiting.indexOf(val) < 0) {
|
||||
exisiting.push(val);
|
||||
}
|
||||
this.form.controls.watchProviders.setValue(exisiting);
|
||||
this.input.nativeElement.value = '';
|
||||
this.control.setValue(null);
|
||||
}
|
||||
|
||||
private _filter(value: string|IWatchProvidersResults): IWatchProvidersResults[] {
|
||||
if (typeof value === 'object') {
|
||||
const filterValue = value.provider_name.toLowerCase();
|
||||
return this.watchProviders.filter(g => g.provider_name.toLowerCase().includes(filterValue));
|
||||
} else if (typeof value === 'string') {
|
||||
const filterValue = value.toLowerCase();
|
||||
return this.watchProviders.filter(g => g.provider_name.toLowerCase().includes(filterValue));
|
||||
}
|
||||
|
||||
return this.watchProviders;
|
||||
}
|
||||
|
||||
}
|
|
@ -41,6 +41,7 @@ import { SidebarModule } from "primeng/sidebar";
|
|||
import { TheMovieDbService } from "../services";
|
||||
import { TranslateModule } from "@ngx-translate/core";
|
||||
import { TruncateModule } from "@yellowspot/ng-truncate";
|
||||
import { WatchProvidersSelectComponent } from "./components/watch-providers-select/watch-providers-select.component";
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
@ -51,6 +52,7 @@ import { TruncateModule } from "@yellowspot/ng-truncate";
|
|||
AdvancedSearchDialogComponent,
|
||||
KeywordSearchComponent,
|
||||
GenreSelectComponent,
|
||||
WatchProvidersSelectComponent,
|
||||
],
|
||||
imports: [
|
||||
SidebarModule,
|
||||
|
@ -99,6 +101,7 @@ import { TruncateModule } from "@yellowspot/ng-truncate";
|
|||
AdvancedSearchDialogComponent,
|
||||
GenreSelectComponent,
|
||||
KeywordSearchComponent,
|
||||
WatchProvidersSelectComponent,
|
||||
DetailsGroupComponent,
|
||||
TruncateModule,
|
||||
InputSwitchModule,
|
||||
|
|
|
@ -46,5 +46,23 @@ namespace Ombi.Controllers.External
|
|||
[HttpGet("Genres/{media}")]
|
||||
public async Task<IEnumerable<Genre>> GetGenres(string media) =>
|
||||
await TmdbApi.GetGenres(media, HttpContext.RequestAborted);
|
||||
|
||||
/// <summary>
|
||||
/// Searches for the watch providers matching the specified term.
|
||||
/// </summary>
|
||||
/// <param name="searchTerm">The search term.</param>
|
||||
[HttpGet("WatchProviders/movie")]
|
||||
public async Task<IEnumerable<WatchProvidersResults>> GetWatchProvidersMovies([FromQuery] string searchTerm) =>
|
||||
await TmdbApi.SearchWatchProviders("movie", searchTerm, HttpContext.RequestAborted);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Searches for the watch providers matching the specified term.
|
||||
/// </summary>
|
||||
/// <param name="searchTerm">The search term.</param>
|
||||
[HttpGet("WatchProviders/tv")]
|
||||
public async Task<IEnumerable<WatchProvidersResults>> GetWatchProvidersTv([FromQuery] string searchTerm) =>
|
||||
await TmdbApi.SearchWatchProviders("tv", searchTerm, HttpContext.RequestAborted);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,6 +183,19 @@ namespace Ombi.Controllers.V2
|
|||
DateTimeOffset.Now.AddHours(12));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns Advanced Searched Media using paging
|
||||
/// </summary>
|
||||
/// <remarks>We use TheMovieDb as the Movie Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpPost("advancedSearch/movie/{currentPosition}/{amountToLoad}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesDefaultResponseType]
|
||||
public Task<IEnumerable<SearchMovieViewModel>> AdvancedSearchMovie([FromBody]DiscoverModel model, int currentPosition, int amountToLoad)
|
||||
{
|
||||
return _movieEngineV2.AdvancedSearch(model, currentPosition, amountToLoad, Request.HttpContext.RequestAborted);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns Seasonal Movies
|
||||
/// </summary>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue