mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-15 01:32:55 -07:00
Fixed the issue with the tv search not working #1463
This commit is contained in:
parent
cd8a44cab8
commit
9f164e4098
12 changed files with 131 additions and 87 deletions
|
@ -7,15 +7,12 @@ namespace Ombi.Core.Engine.Interfaces
|
|||
public interface ITvSearchEngine
|
||||
{
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Search(string searchTerm);
|
||||
|
||||
Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> SearchTreeNode(string searchTerm);
|
||||
Task<TreeNode<SearchTvShowViewModel>> GetShowInformationTreeNode(int tvdbid);
|
||||
Task<SearchTvShowViewModel> GetShowInformation(int tvdbid);
|
||||
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Popular();
|
||||
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Anticipated();
|
||||
|
||||
Task<IEnumerable<SearchTvShowViewModel>> MostWatches();
|
||||
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Trending();
|
||||
Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> Popular();
|
||||
Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> Anticipated();
|
||||
Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> MostWatches();
|
||||
Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> Trending();
|
||||
}
|
||||
}
|
14
src/Ombi.Core/Engine/TreeNode.cs
Normal file
14
src/Ombi.Core/Engine/TreeNode.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.Core.Engine
|
||||
{
|
||||
|
||||
public class TreeNode<T>
|
||||
{
|
||||
public string Label { get; set; }
|
||||
public T Data { get; set; }
|
||||
public List<TreeNode<T>> Children { get; set; }
|
||||
public bool Leaf { get; set; }
|
||||
public bool Expanded { get; set; }
|
||||
}
|
||||
}
|
|
@ -54,6 +54,11 @@ namespace Ombi.Core.Engine
|
|||
return null;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> SearchTreeNode(string searchTerm)
|
||||
{
|
||||
var result = await Search(searchTerm);
|
||||
return result.Select(ParseIntoTreeNode).ToList();
|
||||
}
|
||||
public async Task<SearchTvShowViewModel> GetShowInformation(int tvdbid)
|
||||
{
|
||||
var show = await TvMazeApi.ShowLookupByTheTvDbId(tvdbid);
|
||||
|
@ -100,29 +105,55 @@ namespace Ombi.Core.Engine
|
|||
return await ProcessResult(mapped, existingRequests, plexSettings, embySettings);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SearchTvShowViewModel>> Popular()
|
||||
public async Task<TreeNode<SearchTvShowViewModel>> GetShowInformationTreeNode(int tvdbid)
|
||||
{
|
||||
var result = await GetShowInformation(tvdbid);
|
||||
return ParseIntoTreeNode(result);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> Popular()
|
||||
{
|
||||
var result = await TraktApi.GetPopularShows();
|
||||
return await ProcessResults(result);
|
||||
var processed = await ProcessResults(result);
|
||||
return processed.Select(ParseIntoTreeNode).ToList();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SearchTvShowViewModel>> Anticipated()
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> Anticipated()
|
||||
{
|
||||
var result = await TraktApi.GetAnticipatedShows();
|
||||
return await ProcessResults(result);
|
||||
var processed= await ProcessResults(result);
|
||||
return processed.Select(ParseIntoTreeNode).ToList();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SearchTvShowViewModel>> MostWatches()
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> MostWatches()
|
||||
{
|
||||
var result = await TraktApi.GetMostWatchesShows();
|
||||
return await ProcessResults(result);
|
||||
var processed = await ProcessResults(result);
|
||||
return processed.Select(ParseIntoTreeNode).ToList();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SearchTvShowViewModel>> Trending()
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> Trending()
|
||||
{
|
||||
var result = await TraktApi.GetTrendingShows();
|
||||
return await ProcessResults(result);
|
||||
var processed = await ProcessResults(result);
|
||||
return processed.Select(ParseIntoTreeNode).ToList();
|
||||
}
|
||||
private static TreeNode<SearchTvShowViewModel> ParseIntoTreeNode(SearchTvShowViewModel result)
|
||||
{
|
||||
return new TreeNode<SearchTvShowViewModel>
|
||||
{
|
||||
Data = result,
|
||||
Children = new List<TreeNode<SearchTvShowViewModel>>
|
||||
{
|
||||
new TreeNode<SearchTvShowViewModel>
|
||||
{
|
||||
Data = result, Leaf = true
|
||||
}
|
||||
},
|
||||
Leaf = false
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private async Task<IEnumerable<SearchTvShowViewModel>> ProcessResults<T>(IEnumerable<T> items)
|
||||
{
|
||||
|
@ -180,13 +211,13 @@ namespace Ombi.Core.Engine
|
|||
// Find the existing request season
|
||||
var existingSeason =
|
||||
existingRequestChildRequest.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == season.SeasonNumber);
|
||||
if(existingSeason == null) continue;
|
||||
if (existingSeason == null) continue;
|
||||
|
||||
foreach (var ep in existingSeason.Episodes)
|
||||
{
|
||||
// Find the episode from what we are searching
|
||||
var episodeSearching = season.Episodes.FirstOrDefault(x => x.EpisodeNumber == ep.EpisodeNumber);
|
||||
if(episodeSearching == null)
|
||||
if (episodeSearching == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -51,17 +51,12 @@
|
|||
<a *ngIf="result.trailer" href="{{result.trailer}}" target="_blank"><span class="label label-info">Trailer</span></a>
|
||||
<span *ngIf="result.available" class="label label-success">Available</span>
|
||||
<span *ngIf="result.quality" class="label label-success">{{result.quality}}p</span>
|
||||
<span *ngIf="result.approved && !result.available" class="label label-info">Processing Request</span>
|
||||
<span *ngIf="!result.approved">
|
||||
<span *ngIf="result.requested && !result.available; then requested else notRequested"></span>
|
||||
<ng-template #requested>
|
||||
<span *ngIf="!result.available" class="label label-warning">Pending Approval</span>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #notRequested>
|
||||
<span *ngIf="!result.available" class="label label-danger">Not Yet Requested</span>
|
||||
</ng-template>
|
||||
</span>
|
||||
<ng-template [ngIf]="result.available"><span class="label label-success">Available</span></ng-template>
|
||||
<ng-template [ngIf]="result.approved && !result.available"><span class="label label-info">Processing Request</span></ng-template>
|
||||
<ng-template [ngIf]="result.requested && !result.approved && !result.available"><span class="label label-warning">Pending Approval</span></ng-template>
|
||||
<ng-template [ngIf]="!result.requested && !result.available"><span class="label label-danger">Not Requested</span></ng-template>
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -54,16 +54,10 @@
|
|||
{{ep.airDate | date: 'dd/MM/yyyy' }}
|
||||
</td>
|
||||
<td>
|
||||
<span *ngIf="ep.available" class="label label-success">Available</span>
|
||||
<span *ngIf="ep.approved && !ep.available" class="label label-info">Processing Request</span>
|
||||
<div *ngIf="ep.requested && !ep.available; then requested else notRequested"></div>
|
||||
<ng-template #requested>
|
||||
<span *ngIf="!ep.available" class="label label-warning">Pending Approval</span>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #notRequested>
|
||||
<span *ngIf="!ep.available" class="label label-danger">Not Yet Requested</span>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="ep.available"><span class="label label-success">Available</span></ng-template>
|
||||
<ng-template [ngIf]="ep.approved && !ep.available"><span class="label label-info">Processing Request</span></ng-template>
|
||||
<ng-template [ngIf]="ep.requested && !ep.approved && !ep.available"><span class="label label-warning">Pending Approval</span></ng-template>
|
||||
<ng-template [ngIf]="!ep.requested && !ep.available"><span class="label label-danger">Not Requested</span></ng-template>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
|
|
@ -39,7 +39,6 @@ export class SeriesInformationComponent implements OnInit, OnDestroy {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
public submitRequests() {
|
||||
this.series.requested = true;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<div class="row">
|
||||
<div class="col-sm-2">
|
||||
|
||||
<img *ngIf="node.data.banner" class="img-responsive poster" width="150" [src]="node.data.banner" alt="poster">
|
||||
<img *ngIf="node?.data?.banner" class="img-responsive poster" width="150" [src]="node.data.banner" alt="poster">
|
||||
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
|
@ -56,10 +56,7 @@
|
|||
<span *ngIf="node.data.status" class="label label-primary" target="_blank">{{node.data.status}}</span>
|
||||
|
||||
|
||||
<span *ngIf="node.data.firstAired" class="label label-info" target="_blank">Air Date: {{node.data.firstAired}}</span>
|
||||
|
||||
|
||||
<span *ngIf="node.data.releaseDate" class="label label-info" target="_blank">Release Date: {{node.data.releaseDate | date: 'dd/MM/yyyy'}}</span>
|
||||
<span *ngIf="node.data.firstAired" class="label label-info" target="_blank">Air Date: {{node.data.firstAired | date: 'dd/MM/yyyy'}}</span>
|
||||
|
||||
<span *ngIf="node.data.available" class="label label-success">Available</span>
|
||||
<span *ngIf="node.data.approved && !node.data.available" class="label label-info">Processing Request</span>
|
||||
|
|
|
@ -9,7 +9,7 @@ import { NotificationService } from '../services/notification.service';
|
|||
|
||||
import { ISearchTvResult } from '../interfaces/ISearchTvResult';
|
||||
import { IRequestEngineResult } from '../interfaces/IRequestEngineResult';
|
||||
import { TreeNode } from "primeng/primeng";
|
||||
import { TreeNode } from 'primeng/primeng';
|
||||
|
||||
@Component({
|
||||
selector: 'tv-search',
|
||||
|
@ -21,7 +21,7 @@ export class TvSearchComponent implements OnInit, OnDestroy {
|
|||
private subscriptions = new Subject<void>();
|
||||
searchText: string;
|
||||
searchChanged = new Subject<string>();
|
||||
tvResults: ISearchTvResult[];
|
||||
tvResults: TreeNode[];
|
||||
result: IRequestEngineResult;
|
||||
searchApplied = false;
|
||||
|
||||
|
@ -38,16 +38,16 @@ export class TvSearchComponent implements OnInit, OnDestroy {
|
|||
this.clearResults();
|
||||
return;
|
||||
}
|
||||
this.searchService.searchTv(this.searchText)
|
||||
this.searchService.searchTvTreeNode(this.searchText)
|
||||
.takeUntil(this.subscriptions)
|
||||
.subscribe(x => {
|
||||
this.tvResults = this.transformData(x);
|
||||
this.tvResults = x;
|
||||
this.searchApplied = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
openClosestTab(el: any): void {
|
||||
var rowclass = "undefined";
|
||||
let rowclass = "undefined";
|
||||
el = el.toElement;
|
||||
while (el.className != rowclass) {
|
||||
// Increment the loop to the parent node until we find the row we need
|
||||
|
@ -59,9 +59,9 @@ export class TvSearchComponent implements OnInit, OnDestroy {
|
|||
// the class you specified
|
||||
|
||||
// Then we loop through the children to find the caret which we want to click
|
||||
var caretright = "ui-treetable-toggler fa fa-fw ui-clickable fa-caret-right";
|
||||
var caretdown = "ui-treetable-toggler fa fa-fw ui-clickable fa-caret-down";
|
||||
for (var value of el.children) {
|
||||
let caretright = "ui-treetable-toggler fa fa-fw ui-clickable fa-caret-right";
|
||||
let caretdown = "ui-treetable-toggler fa fa-fw ui-clickable fa-caret-down";
|
||||
for (let value of el.children) {
|
||||
// the caret from the ui has 2 class selectors depending on if expanded or not
|
||||
// we search for both since we want to still toggle the clicking
|
||||
if (value.className === caretright || value.className === caretdown) {
|
||||
|
@ -72,19 +72,6 @@ export class TvSearchComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
};
|
||||
}
|
||||
transformData(datain: ISearchTvResult[]): any {
|
||||
var temp: TreeNode[] = [];
|
||||
datain.forEach(function (value) {
|
||||
temp.push({
|
||||
"data": value,
|
||||
"children": [{
|
||||
"data": value, leaf: true
|
||||
}],
|
||||
leaf: false
|
||||
});
|
||||
}, this)
|
||||
return <TreeNode[]>temp;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.searchText = "";
|
||||
|
@ -143,12 +130,11 @@ export class TvSearchComponent implements OnInit, OnDestroy {
|
|||
|
||||
getExtraInfo() {
|
||||
this.tvResults.forEach((val, index) => {
|
||||
this.searchService.getShowInformation(val.id)
|
||||
this.searchService.getShowInformationTreeNode(val.data.id)
|
||||
.takeUntil(this.subscriptions)
|
||||
.subscribe(x => {
|
||||
this.updateItem(val, x);
|
||||
this.updateItem(val.data, x);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -161,7 +147,6 @@ export class TvSearchComponent implements OnInit, OnDestroy {
|
|||
.takeUntil(this.subscriptions)
|
||||
.subscribe(x => {
|
||||
this.result = x;
|
||||
|
||||
if (this.result.requestAdded) {
|
||||
this.notificationService.success("Request Added",
|
||||
`Request for ${searchResult.title} has been added successfully`);
|
||||
|
@ -171,7 +156,6 @@ export class TvSearchComponent implements OnInit, OnDestroy {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
allSeasons(searchResult: ISearchTvResult) {
|
||||
searchResult.requestAll = true;
|
||||
this.request(searchResult);
|
||||
|
@ -191,11 +175,11 @@ export class TvSearchComponent implements OnInit, OnDestroy {
|
|||
this.route.navigate(['/search/show', searchResult.id]);
|
||||
}
|
||||
|
||||
private updateItem(key: ISearchTvResult, updated: ISearchTvResult) {
|
||||
var index = this.tvResults.indexOf(key, 0);
|
||||
if (index > -1) {
|
||||
this.tvResults[index] = updated;
|
||||
}
|
||||
private updateItem(key: TreeNode, updated: TreeNode) {
|
||||
let item = this.tvResults.filter((val) => {
|
||||
return val.data == key;
|
||||
});
|
||||
item[0].data = updated.data;
|
||||
}
|
||||
|
||||
private clearResults() {
|
||||
|
|
|
@ -5,6 +5,7 @@ import { Observable } from 'rxjs/Rx';
|
|||
import { ServiceAuthHelpers } from './service.helpers';
|
||||
import { ISearchMovieResult } from '../interfaces/ISearchMovieResult';
|
||||
import { ISearchTvResult } from '../interfaces/ISearchTvResult';
|
||||
import { TreeNode } from "primeng/primeng";
|
||||
|
||||
@Injectable()
|
||||
export class SearchService extends ServiceAuthHelpers {
|
||||
|
@ -37,21 +38,28 @@ export class SearchService extends ServiceAuthHelpers {
|
|||
searchTv(searchTerm: string): Observable<ISearchTvResult[]> {
|
||||
return this.http.get(`${this.url}/Tv/` + searchTerm).map(this.extractData);
|
||||
}
|
||||
searchTvTreeNode(searchTerm: string): Observable<TreeNode[]> {
|
||||
return this.http.get(`${this.url}/Tv/${searchTerm}/tree`).map(this.extractData);
|
||||
}
|
||||
|
||||
getShowInformationTreeNode(theTvDbId: number): Observable<TreeNode> {
|
||||
return this.http.get(`${this.url}/Tv/info/${theTvDbId}/Tree`).map(this.extractData);
|
||||
}
|
||||
|
||||
getShowInformation(theTvDbId: number): Observable<ISearchTvResult> {
|
||||
return this.http.get(`${this.url}/Tv/info/${theTvDbId}`).map(this.extractData);
|
||||
}
|
||||
|
||||
popularTv(): Observable<ISearchTvResult[]> {
|
||||
popularTv(): Observable<TreeNode[]> {
|
||||
return this.http.get(`${this.url}/Tv/popular`).map(this.extractData);
|
||||
}
|
||||
mostWatchedTv(): Observable<ISearchTvResult[]> {
|
||||
mostWatchedTv(): Observable<TreeNode[]> {
|
||||
return this.http.get(`${this.url}/Tv/mostwatched`).map(this.extractData);
|
||||
}
|
||||
anticipatedTv(): Observable<ISearchTvResult[]> {
|
||||
anticipatedTv(): Observable<TreeNode[]> {
|
||||
return this.http.get(`${this.url}/Tv/anticipated`).map(this.extractData);
|
||||
}
|
||||
trendingTv(): Observable<ISearchTvResult[]> {
|
||||
trendingTv(): Observable<TreeNode[]> {
|
||||
return this.http.get(`${this.url}/Tv/trending`).map(this.extractData);
|
||||
}
|
||||
}
|
|
@ -113,6 +113,30 @@ namespace Ombi.Controllers
|
|||
return await TvEngine.Search(searchTerm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for a Tv Show.
|
||||
/// </summary>
|
||||
/// <param name="searchTerm">The search term.</param>
|
||||
/// <remarks>We use TvMaze as the Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/{searchTerm}/tree")]
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> SearchTvTreeNode(string searchTerm)
|
||||
{
|
||||
return await TvEngine.SearchTreeNode(searchTerm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets extra show information.
|
||||
/// </summary>
|
||||
/// <param name="tvdbId">The TVDB identifier.</param>
|
||||
/// <remarks>We use TvMaze as the Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/info/{tvdbId}/tree")]
|
||||
public async Task<TreeNode<SearchTvShowViewModel>> GetShowInfoTreeNode(int tvdbId)
|
||||
{
|
||||
return await TvEngine.GetShowInformationTreeNode(tvdbId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets extra show information.
|
||||
/// </summary>
|
||||
|
@ -131,7 +155,7 @@ namespace Ombi.Controllers
|
|||
/// <remarks>We use Trakt.tv as the Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/popular")]
|
||||
public async Task<IEnumerable<SearchTvShowViewModel>> PopularTv()
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> PopularTv()
|
||||
{
|
||||
return await TvEngine.Popular();
|
||||
}
|
||||
|
@ -141,7 +165,7 @@ namespace Ombi.Controllers
|
|||
/// <remarks>We use Trakt.tv as the Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/anticipated")]
|
||||
public async Task<IEnumerable<SearchTvShowViewModel>> AnticiplatedTv()
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> AnticiplatedTv()
|
||||
{
|
||||
return await TvEngine.Anticipated();
|
||||
}
|
||||
|
@ -151,7 +175,7 @@ namespace Ombi.Controllers
|
|||
/// <remarks>We use Trakt.tv as the Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/mostwatched")]
|
||||
public async Task<IEnumerable<SearchTvShowViewModel>> MostWatched()
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> MostWatched()
|
||||
{
|
||||
return await TvEngine.MostWatches();
|
||||
}
|
||||
|
@ -161,7 +185,7 @@ namespace Ombi.Controllers
|
|||
/// <remarks>We use Trakt.tv as the Provider</remarks>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/trending")]
|
||||
public async Task<IEnumerable<SearchTvShowViewModel>> Trending()
|
||||
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> Trending()
|
||||
{
|
||||
return await TvEngine.Trending();
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<RuntimeIdentifiers>win10-x64;osx.10.12-x64;ubuntu.16.04-x64;debian.8-x64;centos.7-x64;</RuntimeIdentifiers>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
<TypeScriptToolsVersion>2.5</TypeScriptToolsVersion>
|
||||
<TypeScriptToolsVersion>2.3</TypeScriptToolsVersion>
|
||||
<AssemblyVersion>$(SemVer)</AssemblyVersion>
|
||||
<FileVersion>$(SemVer)</FileVersion>
|
||||
<Version>$(FullVer)</Version>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #1f1f1f;
|
||||
}
|
||||
|
||||
.app-loading {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue