diff --git a/Ombi/Ombi.Api.TvMaze/Models/TvMazeShow.cs b/Ombi/Ombi.Api.TvMaze/Models/TvMazeShow.cs index ce0572410..e537864e9 100644 --- a/Ombi/Ombi.Api.TvMaze/Models/TvMazeShow.cs +++ b/Ombi/Ombi.Api.TvMaze/Models/TvMazeShow.cs @@ -34,7 +34,7 @@ namespace Ombi.Api.TvMaze.Models public class TvMazeCustomSeason { public int SeasonNumber { get; set; } - public int EpisodeNumber { get; set; } + public List EpisodeNumber { get; set; } } public class Season diff --git a/Ombi/Ombi.Api.TvMaze/TvMazeApi.cs b/Ombi/Ombi.Api.TvMaze/TvMazeApi.cs index f94ad2774..4be0f2658 100644 --- a/Ombi/Ombi.Api.TvMaze/TvMazeApi.cs +++ b/Ombi/Ombi.Api.TvMaze/TvMazeApi.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -60,11 +61,25 @@ namespace Ombi.Api.TvMaze foreach (var e in episodes) { - obj.Season.Add(new TvMazeCustomSeason + // Check if the season exists + var currentSeason = obj.Season.FirstOrDefault(x => x.SeasonNumber == e.season); + + if (currentSeason == null) + { + // Create the season + obj.Season.Add(new TvMazeCustomSeason + { + SeasonNumber = e.season, + EpisodeNumber = new List {e.number} + }); + } + else { - SeasonNumber = e.season, - EpisodeNumber = e.number - }); + // Just add a new episode into that season + currentSeason.EpisodeNumber.Add(e.number); + } + + } return obj; diff --git a/Ombi/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs b/Ombi/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs index 5e08ccb3d..9d86d8dc9 100644 --- a/Ombi/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs +++ b/Ombi/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs @@ -2,11 +2,13 @@ using System.Threading.Tasks; using Ombi.Core.Models.Search; -namespace Ombi.Core.Engine +namespace Ombi.Core.Engine.Interfaces { public interface ITvSearchEngine { Task> Search(string searchTerm); + + Task GetShowInformation(int tvdbId); //Task> Popular(); //Task> Anticipated(); //Task> MostWatches(); diff --git a/Ombi/Ombi.Core/Engine/TvRequestEngine.cs b/Ombi/Ombi.Core/Engine/TvRequestEngine.cs index a75550495..1dff36ab5 100644 --- a/Ombi/Ombi.Core/Engine/TvRequestEngine.cs +++ b/Ombi/Ombi.Core/Engine/TvRequestEngine.cs @@ -49,10 +49,32 @@ namespace Ombi.Core.Engine ImdbId = showInfo.externals?.imdb ?? string.Empty, TvDbId = tv.Id.ToString(), ProviderId = tv.Id, - SeasonsNumbersRequested = tv.SeasonNumbersRequested, RequestAll = tv.RequestAll }; + if (tv.LatestSeason) + { + var latest = showInfo.Season.OrderBy(x => x).FirstOrDefault(); + model.SeasonRequests = showInfo.Season.Any() + ? new List {new SeasonRequestModel + { + SeasonNumber = latest.SeasonNumber, + Episodes = latest.EpisodeNumber + }} + : new List(); + } + if (tv.FirstSeason) + { + var first = showInfo.Season.OrderByDescending(x => x).FirstOrDefault(); + model.SeasonRequests = showInfo.Season.Any() + ? new List {new SeasonRequestModel + { + SeasonNumber = first.SeasonNumber, + Episodes = first.EpisodeNumber + }} + : new List(); + } + var existingRequest = await TvRequestService.CheckRequestAsync(model.Id); if (existingRequest != null) @@ -104,13 +126,13 @@ namespace Ombi.Core.Engine private async Task AddExistingRequest(TvRequestModel newRequest, TvRequestModel existingRequest) { - var episodeDifference = new List(); + var episodeDifference = new List(); if (existingRequest.HasChildRequests) { // Let's check if this has already been requested as a child! foreach (var children in existingRequest.ChildRequests) { - var difference = GetListDifferences(children.Episodes, newRequest.Episodes).ToList(); + var difference = GetListDifferences(children.SeasonRequests, newRequest.SeasonRequests).ToList(); if (difference.Any()) { episodeDifference = difference; @@ -121,7 +143,7 @@ namespace Ombi.Core.Engine if (episodeDifference.Any()) { // This is where there are some episodes that have been requested, but this list contains the 'new' requests - newRequest.Episodes = episodeDifference; + newRequest.SeasonRequests = episodeDifference; } existingRequest.ChildRequests.Add(newRequest); @@ -132,17 +154,17 @@ namespace Ombi.Core.Engine { // TODO Auto Approval Code } - return await AddRequest(newRequest); + return await AfterRequest(newRequest); } - private IEnumerable GetListDifferences(IEnumerable existing, IEnumerable request) + private IEnumerable GetListDifferences(IEnumerable existing, IEnumerable request) { var newRequest = request .Select(r => - new EpisodesModel + new SeasonRequestModel { SeasonNumber = r.SeasonNumber, - EpisodeNumber = r.EpisodeNumber + Episodes = r.Episodes }).ToList(); return newRequest.Except(existing); @@ -152,6 +174,11 @@ namespace Ombi.Core.Engine { await TvRequestService.AddRequestAsync(model); + return await AfterRequest(model); + } + + private async Task AfterRequest(BaseRequestModel model) + { if (ShouldSendNotification(model.Type)) { var notificationModel = new NotificationModel diff --git a/Ombi/Ombi.Core/Engine/TvSearchEngine.cs b/Ombi/Ombi.Core/Engine/TvSearchEngine.cs index c0ce76550..9eedb5a31 100644 --- a/Ombi/Ombi.Core/Engine/TvSearchEngine.cs +++ b/Ombi/Ombi.Core/Engine/TvSearchEngine.cs @@ -5,6 +5,8 @@ using System.Threading.Tasks; using AutoMapper; using Ombi.Api.Trakt; using Ombi.Api.TvMaze; +using Ombi.Api.TvMaze.Models; +using Ombi.Core.Engine.Interfaces; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Core.Requests.Models; @@ -46,6 +48,12 @@ namespace Ombi.Core.Engine return null; } + public async Task GetShowInformation(int tvdbId) + { + var show = await TvMazeApi.ShowLookupByTheTvDbId(tvdbId); + return Mapper.Map(show); + } + //public async Task> Popular() //{ // var result = await TraktApi.GetPopularShows(); @@ -113,7 +121,7 @@ namespace Ombi.Core.Engine var dbt = existingRequests[tvdbid]; item.Requested = true; - item.EpisodesRequested = dbt.Episodes.ToList(); + item.SeasonRequests = dbt.SeasonRequests.ToList(); item.Approved = dbt.Approved; } //if (sonarrCached.Select(x => x.TvdbId).Contains(tvdbid) || sickRageCache.Contains(tvdbid)) diff --git a/Ombi/Ombi.Core/Models/Requests/RequestModel.cs b/Ombi/Ombi.Core/Models/Requests/RequestModel.cs index bae2c760c..cc4aecf2a 100644 --- a/Ombi/Ombi.Core/Models/Requests/RequestModel.cs +++ b/Ombi/Ombi.Core/Models/Requests/RequestModel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Ombi.Store.Entities; namespace Ombi.Core.Models.Requests @@ -54,4 +55,11 @@ namespace Ombi.Core.Models.Requests return hashSeason + hashEp; } } + + public class SeasonRequestModel + { + public int SeasonNumber { get; set; } + public List Episodes { get; set; } + } + } \ No newline at end of file diff --git a/Ombi/Ombi.Core/Models/Requests/Tv/TvRequestModel.cs b/Ombi/Ombi.Core/Models/Requests/Tv/TvRequestModel.cs index d7a6c997e..323137305 100644 --- a/Ombi/Ombi.Core/Models/Requests/Tv/TvRequestModel.cs +++ b/Ombi/Ombi.Core/Models/Requests/Tv/TvRequestModel.cs @@ -6,15 +6,14 @@ namespace Ombi.Core.Models.Requests { public TvRequestModel() { - Episodes = new List(); + SeasonRequests = new List(); ChildRequests = new List(); } public string ImdbId { get; set; } public string TvDbId { get; set; } public bool RequestAll { get; set; } - public List SeasonsNumbersRequested { get; set; } - public List Episodes { get; set; } + public List SeasonRequests { get; set; } /// /// This is for TV requests, If there is more than 1 request for a show then it should be a child diff --git a/Ombi/Ombi.Core/Models/Search/SearchTvShowViewModel.cs b/Ombi/Ombi.Core/Models/Search/SearchTvShowViewModel.cs index 4da0f1cdc..12b2d0556 100644 --- a/Ombi/Ombi.Core/Models/Search/SearchTvShowViewModel.cs +++ b/Ombi/Ombi.Core/Models/Search/SearchTvShowViewModel.cs @@ -39,22 +39,14 @@ namespace Ombi.Core.Models.Search /// public string Homepage { get; set; } - /// - /// This is for when the users requests multiple seasons or a single season - /// - public List SeasonNumbersRequested { get; set; } = new List(); - - /// - /// If we have requested some episodes - /// - public List EpisodesRequested { get; set; } = new List(); + public List SeasonRequests { get; set; } = new List(); /// /// If we are requesting the entire series /// public bool RequestAll { get; set; } - public bool SpecificSeasonsRequested => SeasonNumbersRequested.Count > 0; - public bool SpecificEpisodesRequested => EpisodesRequested.Count > 0; + public bool FirstSeason { get; set; } + public bool LatestSeason { get; set; } } } \ No newline at end of file diff --git a/Ombi/Ombi.DependencyInjection/IocExtensions.cs b/Ombi/Ombi.DependencyInjection/IocExtensions.cs index bf41f6350..48f954cb8 100644 --- a/Ombi/Ombi.DependencyInjection/IocExtensions.cs +++ b/Ombi/Ombi.DependencyInjection/IocExtensions.cs @@ -1,10 +1,6 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Security.Principal; +using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Ombi.Api.Emby; using Ombi.Api.Plex; @@ -13,6 +9,7 @@ using Ombi.Api.TheMovieDb; using Ombi.Api.TvMaze; using Ombi.Core; using Ombi.Core.Engine; +using Ombi.Core.Engine.Interfaces; using Ombi.Core.IdentityResolver; using Ombi.Core.Models.Requests; using Ombi.Core.Requests.Models; @@ -23,14 +20,13 @@ using Ombi.Schedule.Jobs; using Ombi.Settings.Settings; using Ombi.Store.Context; using Ombi.Store.Repository; -using Ombi.TheMovieDbApi; namespace Ombi.DependencyInjection { [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class IocExtensions { - public static IServiceCollection RegisterDependencies(this IServiceCollection services) + public static void RegisterDependencies(this IServiceCollection services) { services.RegisterEngines(); services.RegisterApi(); @@ -38,30 +34,26 @@ namespace Ombi.DependencyInjection services.RegisterStore(); services.RegisterIdentity(); services.RegisterJobs(); - - return services; } - public static IServiceCollection RegisterEngines(this IServiceCollection services) + public static void RegisterEngines(this IServiceCollection services) { services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); - return services; } - public static IServiceCollection RegisterApi(this IServiceCollection services) + public static void RegisterApi(this IServiceCollection services) { services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); - return services; } - public static IServiceCollection RegisterStore(this IServiceCollection services) + public static void RegisterStore(this IServiceCollection services) { services.AddEntityFrameworkSqlite().AddDbContext(); @@ -72,29 +64,22 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(typeof(ISettingsService<>), typeof(SettingsServiceV2<>)); - return services; } - public static IServiceCollection RegisterServices(this IServiceCollection services) + public static void RegisterServices(this IServiceCollection services) { - services.AddTransient(); services.AddTransient(typeof(IRequestService<>), typeof(JsonRequestService<>)); services.AddSingleton(); - - return services; } - public static IServiceCollection RegisterJobs(this IServiceCollection services) + public static void RegisterJobs(this IServiceCollection services) { services.AddTransient(); services.AddTransient(); - - return services; } - public static IServiceCollection RegisterIdentity(this IServiceCollection services) + public static void RegisterIdentity(this IServiceCollection services) { - services.AddTransient(); services.AddAuthorization(auth => { @@ -102,7 +87,6 @@ namespace Ombi.DependencyInjection .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser().Build()); }); - return services; } } } diff --git a/Ombi/Ombi.Helpers/LoggingEvents.cs b/Ombi/Ombi.Helpers/LoggingEvents.cs index 00fa0ee01..acdab07c4 100644 --- a/Ombi/Ombi.Helpers/LoggingEvents.cs +++ b/Ombi/Ombi.Helpers/LoggingEvents.cs @@ -5,5 +5,6 @@ namespace Ombi.Helpers public class LoggingEvents { public static EventId ApiException => new EventId(1000); + public static EventId CacherException => new EventId(2000); } } \ No newline at end of file diff --git a/Ombi/Ombi.Mapping/Profiles/TvProfile.cs b/Ombi/Ombi.Mapping/Profiles/TvProfile.cs index 9ab3483f1..3a20f46c4 100644 --- a/Ombi/Ombi.Mapping/Profiles/TvProfile.cs +++ b/Ombi/Ombi.Mapping/Profiles/TvProfile.cs @@ -2,6 +2,7 @@ using System.Globalization; using AutoMapper; using Ombi.Api.TvMaze.Models; +using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Helpers; //using TraktApiSharp.Objects.Get.Shows; @@ -24,9 +25,26 @@ namespace Ombi.Mapping.Profiles .ForMember(dest => dest.Runtime, opts => opts.MapFrom(src => src.show.runtime.ToString())) .ForMember(dest => dest.SeriesId, opts => opts.MapFrom(src => src.show.id)) .ForMember(dest => dest.SeriesName, opts => opts.MapFrom(src => src.show.name)) - .ForMember(dest => dest.Banner, opts => opts.MapFrom(src => !string.IsNullOrEmpty(src.show.image.medium) ? src.show.image.medium.Replace("http","https") : string.Empty)) + .ForMember(dest => dest.Banner, opts => opts.MapFrom(src => !string.IsNullOrEmpty(src.show.image.medium) ? src.show.image.medium.Replace("http", "https") : string.Empty)) .ForMember(dest => dest.Status, opts => opts.MapFrom(src => src.show.status)); + CreateMap() + .ConstructUsing(x => new SeasonRequestModel { Episodes = x.EpisodeNumber, SeasonNumber = x.SeasonNumber }); + CreateMap() + .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.externals.thetvdb)) + .ForMember(dest => dest.FirstAired, opts => opts.MapFrom(src => src.premiered)) + .ForMember(dest => dest.ImdbId, opts => opts.MapFrom(src => src.externals.imdb)) + .ForMember(dest => dest.Network, opts => opts.MapFrom(src => src.network.name)) + .ForMember(dest => dest.NetworkId, opts => opts.MapFrom(src => src.network.id.ToString())) + .ForMember(dest => dest.Overview, opts => opts.MapFrom(src => src.summary.RemoveHtml())) + .ForMember(dest => dest.Rating, opts => opts.MapFrom(src => src.rating.ToString())) + .ForMember(dest => dest.Runtime, opts => opts.MapFrom(src => src.runtime.ToString(CultureInfo.CurrentUICulture))) + .ForMember(dest => dest.SeriesId, opts => opts.MapFrom(src => src.id)) + .ForMember(dest => dest.SeriesName, opts => opts.MapFrom(src => src.name)) + .ForMember(dest => dest.Banner, opts => opts.MapFrom(src => !string.IsNullOrEmpty(src.image.medium) ? src.image.medium.Replace("http", "https") : string.Empty)) + .ForMember(dest => dest.Status, opts => opts.MapFrom(src => src.status)) + .ForMember(dest => dest.SeasonRequests, opts => opts.MapFrom(src => src.Season)); + //CreateMap() // .ForMember(dest => dest.Id, opts => opts.MapFrom(src => Convert.ToInt32(src.Ids.Tvdb.ToString()))) // .ForMember(dest => dest.FirstAired, opts => opts.MapFrom(src => src.FirstAired.HasValue ? src.FirstAired.Value.ToString("yyyy-MM-ddTHH:mm:ss") : string.Empty)) diff --git a/Ombi/Ombi.Schedule/Jobs/PlexContentCacher.cs b/Ombi/Ombi.Schedule/Jobs/PlexContentCacher.cs index 9459bb657..3289434fc 100644 --- a/Ombi/Ombi.Schedule/Jobs/PlexContentCacher.cs +++ b/Ombi/Ombi.Schedule/Jobs/PlexContentCacher.cs @@ -68,13 +68,14 @@ namespace Ombi.Schedule.Jobs } Logger.LogInformation("Starting Plex Content Cacher"); - //TODO - StartTheCache(plexSettings).Wait(); + try + { - //if (libraries == null || !libraries.Any()) - //{ - // return; - //} + StartTheCache(plexSettings).Wait(); + } + catch (Exception e) { + Logger.LogWarning(LoggingEvents.CacherException, e, "Exception thrown when attempting to cache the Plex Content"); + } } //private List CachedLibraries(PlexSettings plexSettings) //{ @@ -122,9 +123,9 @@ namespace Ombi.Schedule.Jobs // Let's now process this. + var contentToAdd = new List(); foreach (var content in allContent) { - var contentToAdd = new List(); if (content.viewGroup.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase)) { // Process Shows @@ -188,6 +189,11 @@ namespace Ombi.Schedule.Jobs } } } + + if (contentToAdd.Any()) + { + await Repo.AddRange(contentToAdd); + } } private List GetAllContent(PlexSettings plexSettings) diff --git a/Ombi/Ombi.Store/Repository/IPlexContentRepository.cs b/Ombi/Ombi.Store/Repository/IPlexContentRepository.cs index 8cd1211ed..41e9456ac 100644 --- a/Ombi/Ombi.Store/Repository/IPlexContentRepository.cs +++ b/Ombi/Ombi.Store/Repository/IPlexContentRepository.cs @@ -7,6 +7,7 @@ namespace Ombi.Store.Repository public interface IPlexContentRepository { Task Add(PlexContent content); + Task AddRange(IEnumerable content); Task ContentExists(string providerId); Task> GetAll(); Task Get(string providerId); diff --git a/Ombi/Ombi.Store/Repository/PlexContentRepository.cs b/Ombi/Ombi.Store/Repository/PlexContentRepository.cs index 76ba16200..0a0ada0fb 100644 --- a/Ombi/Ombi.Store/Repository/PlexContentRepository.cs +++ b/Ombi/Ombi.Store/Repository/PlexContentRepository.cs @@ -48,6 +48,12 @@ namespace Ombi.Store.Repository return await Db.PlexContent.ToListAsync(); } + public async Task AddRange(IEnumerable content) + { + await Db.PlexContent.AddRangeAsync(content); + await Db.SaveChangesAsync(); + } + public async Task ContentExists(string providerId) { return await Db.PlexContent.AnyAsync(x => x.ProviderId == providerId); diff --git a/Ombi/Ombi/Controllers/SearchController.cs b/Ombi/Ombi/Controllers/SearchController.cs index 3ecccc264..e98a2bd70 100644 --- a/Ombi/Ombi/Controllers/SearchController.cs +++ b/Ombi/Ombi/Controllers/SearchController.cs @@ -7,6 +7,7 @@ using Microsoft.Extensions.Logging; using Ombi.Core; using Ombi.Core.Engine; +using Ombi.Core.Engine.Interfaces; using Ombi.Core.Models.Search; namespace Ombi.Controllers @@ -65,6 +66,12 @@ namespace Ombi.Controllers return await TvEngine.Search(searchTerm); } + [HttpGet("tv/seasons/{tvdbId}")] + public async Task> GetSeasons(int tvdbId) + { + return await TvEngine.GetSeasons(tvdbId); + } + //[HttpGet("tv/popular")] //public async Task> PopularTv() //{ diff --git a/Ombi/Ombi/wwwroot/app/interfaces/IRequestModel.ts b/Ombi/Ombi/wwwroot/app/interfaces/IRequestModel.ts index ed0c2d7ab..f6f82683c 100644 --- a/Ombi/Ombi/wwwroot/app/interfaces/IRequestModel.ts +++ b/Ombi/Ombi/wwwroot/app/interfaces/IRequestModel.ts @@ -1,6 +1,5 @@ -import { IEpisodeModel }from "./ISearchTvResult"; - -export interface IMediaBase { +export interface IMediaBase { + imdbId: string, id: number, providerId: number, title: string, @@ -23,21 +22,27 @@ export interface IMediaBase { } export interface IMovieRequestModel extends IMediaBase { - imdbId: string, + } export interface ITvRequestModel extends IMediaBase { imdbId: string, tvDbId: string, requestAll: boolean, - seasonNumbersRequested: number[], - episodes: IEpisodeModel[], + seasonRequests: ISeasonRequests[], childRequests: ITvRequestModel[], hasChildRequests: boolean, rootFolderSelected: number, firstAired:string, } +export interface ISeasonRequests +{ + seasonNumber: number, + episodes:number[], +} + + export enum RequestType { movie = 1, tvShow = 2 diff --git a/Ombi/Ombi/wwwroot/app/interfaces/ISearchTvResult.ts b/Ombi/Ombi/wwwroot/app/interfaces/ISearchTvResult.ts index 146a246fa..7f30f9c4b 100644 --- a/Ombi/Ombi/wwwroot/app/interfaces/ISearchTvResult.ts +++ b/Ombi/Ombi/wwwroot/app/interfaces/ISearchTvResult.ts @@ -1,4 +1,6 @@ -export interface ISearchTvResult { +import { ISeasonRequests } from "./IRequestModel"; + +export interface ISearchTvResult { id: number, seriesName: string, aliases: string[], @@ -19,17 +21,12 @@ siteRating: number, trailer: string, homepage:string, - episodesRequested: IEpisodeModel[], - seasonNumbersRequested: number[], + seasonsRequested: ISeasonRequests[], requestAll:boolean, approved: boolean, requested: boolean, available: boolean, plexUrl: string, - + firstSeason: boolean, + latestSeason:boolean, } - -export interface IEpisodeModel { - seasonNumber: number, - episodeNumber:number, -} \ No newline at end of file diff --git a/Ombi/Ombi/wwwroot/app/requests/movierequests.component.ts b/Ombi/Ombi/wwwroot/app/requests/movierequests.component.ts index b39878468..6e544e6c1 100644 --- a/Ombi/Ombi/wwwroot/app/requests/movierequests.component.ts +++ b/Ombi/Ombi/wwwroot/app/requests/movierequests.component.ts @@ -1,8 +1,9 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { Subject } from 'rxjs/Subject'; import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/distinctUntilChanged'; import 'rxjs/add/operator/map'; +import 'rxjs/add/operator/takeUntil'; import 'rxjs/add/operator/debounceTime'; @@ -19,18 +20,21 @@ import { IMovieRequestModel } from '../interfaces/IRequestModel'; moduleId: module.id, templateUrl: './movierequests.component.html' }) -export class MovieRequestsComponent implements OnInit { +export class MovieRequestsComponent implements OnInit, OnDestroy { constructor(private requestService: RequestService, private identityService: IdentityService) { this.searchChanged .debounceTime(600) // Wait Xms afterthe last event before emitting last event .distinctUntilChanged() // only emit if value is different from previous value + .takeUntil(this.subscriptions) .subscribe(x => { this.searchText = x as string; if (this.searchText === "") { this.resetSearch(); return; } - this.requestService.searchMovieRequests(this.searchText).subscribe(m => this.movieRequests = m); + this.requestService.searchMovieRequests(this.searchText) + .takeUntil(this.subscriptions) + .subscribe(m => this.movieRequests = m); }); } @@ -39,10 +43,13 @@ export class MovieRequestsComponent implements OnInit { searchChanged: Subject = new Subject(); searchText: string; - isAdmin : boolean; + isAdmin: boolean; private currentlyLoaded: number; - private amountToLoad : number; + private amountToLoad: number; + + + private subscriptions = new Subject(); ngOnInit() { this.amountToLoad = 5; @@ -50,13 +57,15 @@ export class MovieRequestsComponent implements OnInit { this.loadInit(); } - + loadMore() { - this.requestService.getMovieRequests(this.amountToLoad, this.currentlyLoaded + 1).subscribe(x => { - this.movieRequests.push.apply(this.movieRequests, x); - this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad; - }); + this.requestService.getMovieRequests(this.amountToLoad, this.currentlyLoaded + 1) + .takeUntil(this.subscriptions) + .subscribe(x => { + this.movieRequests.push.apply(this.movieRequests, x); + this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad; + }); } search(text: any) { @@ -70,7 +79,7 @@ export class MovieRequestsComponent implements OnInit { changeAvailability(request: IMovieRequestModel, available: boolean) { request.available = available; - + this.updateRequest(request); } @@ -87,11 +96,15 @@ export class MovieRequestsComponent implements OnInit { } private updateRequest(request: IMovieRequestModel) { - this.requestService.updateMovieRequest(request).subscribe(x => request = x); + this.requestService.updateMovieRequest(request) + .takeUntil(this.subscriptions) + .subscribe(x => request = x); } private loadInit() { - this.requestService.getMovieRequests(this.amountToLoad, 0).subscribe(x => this.movieRequests = x); + this.requestService.getMovieRequests(this.amountToLoad, 0) + .takeUntil(this.subscriptions) + .subscribe(x => this.movieRequests = x); this.isAdmin = this.identityService.hasRole("Admin"); } @@ -106,4 +119,9 @@ export class MovieRequestsComponent implements OnInit { this.movieRequests.splice(index, 1); } } + + ngOnDestroy(): void { + this.subscriptions.next(); + this.subscriptions.complete(); + } } \ No newline at end of file diff --git a/Ombi/Ombi/wwwroot/app/requests/tvrequests.component.html b/Ombi/Ombi/wwwroot/app/requests/tvrequests.component.html index db2fd905c..080c7a406 100644 --- a/Ombi/Ombi/wwwroot/app/requests/tvrequests.component.html +++ b/Ombi/Ombi/wwwroot/app/requests/tvrequests.component.html @@ -84,6 +84,7 @@

Requested By: {{user}}
+
Seasons Requested: {{s}}
Request status: Available diff --git a/Ombi/Ombi/wwwroot/app/requests/tvrequests.component.ts b/Ombi/Ombi/wwwroot/app/requests/tvrequests.component.ts index 2ea70e328..b63aa5646 100644 --- a/Ombi/Ombi/wwwroot/app/requests/tvrequests.component.ts +++ b/Ombi/Ombi/wwwroot/app/requests/tvrequests.component.ts @@ -1,8 +1,9 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { Subject } from 'rxjs/Subject'; import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/distinctUntilChanged'; import 'rxjs/add/operator/map'; +import "rxjs/add/operator/takeUntil"; import 'rxjs/add/operator/debounceTime'; @@ -19,30 +20,37 @@ import { ITvRequestModel } from '../interfaces/IRequestModel'; moduleId: module.id, templateUrl: './tvrequests.component.html' }) -export class TvRequestsComponent implements OnInit { +export class TvRequestsComponent implements OnInit, OnDestroy { constructor(private requestService: RequestService, private identityService: IdentityService) { this.searchChanged .debounceTime(600) // Wait Xms afterthe last event before emitting last event .distinctUntilChanged() // only emit if value is different from previous value + .takeUntil(this.subscriptions) .subscribe(x => { this.searchText = x as string; if (this.searchText === "") { this.resetSearch(); return; } - this.requestService.searchTvRequests(this.searchText).subscribe(m => this.tvRequests = m); + this.requestService.searchTvRequests(this.searchText) + .takeUntil(this.subscriptions) + .subscribe(m => this.tvRequests = m); }); } + + private subscriptions = new Subject(); + tvRequests: ITvRequestModel[]; searchChanged = new Subject(); searchText: string; - isAdmin : boolean; + isAdmin: boolean; private currentlyLoaded: number; - private amountToLoad : number; + private amountToLoad: number; + ngOnInit() { this.amountToLoad = 5; @@ -50,13 +58,15 @@ export class TvRequestsComponent implements OnInit { this.loadInit(); } - + loadMore() { - this.requestService.getTvRequests(this.amountToLoad, this.currentlyLoaded + 1).subscribe(x => { - this.tvRequests.push.apply(this.tvRequests, x); - this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad; - }); + this.requestService.getTvRequests(this.amountToLoad, this.currentlyLoaded + 1) + .takeUntil(this.subscriptions) + .subscribe(x => { + this.tvRequests.push.apply(this.tvRequests, x); + this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad; + }); } search(text: any) { @@ -70,7 +80,7 @@ export class TvRequestsComponent implements OnInit { changeAvailability(request: ITvRequestModel, available: boolean) { request.available = available; - + this.updateRequest(request); } @@ -87,13 +97,17 @@ export class TvRequestsComponent implements OnInit { } private updateRequest(request: ITvRequestModel) { - this.requestService.updateTvRequest(request).subscribe(x => request = x); + this.requestService.updateTvRequest(request) + .takeUntil(this.subscriptions) + .subscribe(x => request = x); } private loadInit() { - this.requestService.getTvRequests(this.amountToLoad, 0).subscribe(x => { - this.tvRequests = x; - }); + this.requestService.getTvRequests(this.amountToLoad, 0) + .takeUntil(this.subscriptions) + .subscribe(x => { + this.tvRequests = x; + }); this.isAdmin = this.identityService.hasRole("Admin"); } @@ -108,4 +122,9 @@ export class TvRequestsComponent implements OnInit { this.tvRequests.splice(index, 1); } } + + ngOnDestroy(): void { + this.subscriptions.next(); + this.subscriptions.complete(); + } } \ No newline at end of file diff --git a/Ombi/Ombi/wwwroot/app/search/moviesearch.component.ts b/Ombi/Ombi/wwwroot/app/search/moviesearch.component.ts index 9717bdb8f..c3a9f6f0e 100644 --- a/Ombi/Ombi/wwwroot/app/search/moviesearch.component.ts +++ b/Ombi/Ombi/wwwroot/app/search/moviesearch.component.ts @@ -1,8 +1,9 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { Subject } from 'rxjs/Subject'; import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/distinctUntilChanged'; import 'rxjs/add/operator/map'; +import "rxjs/add/operator/takeUntil"; import { SearchService } from '../services/search.service'; import { RequestService } from '../services/request.service'; @@ -16,31 +17,35 @@ import { IRequestEngineResult } from '../interfaces/IRequestEngineResult'; moduleId: module.id, templateUrl: './moviesearch.component.html', }) -export class MovieSearchComponent implements OnInit { +export class MovieSearchComponent implements OnInit, OnDestroy { searchText: string; + private subscriptions = new Subject(); searchChanged: Subject = new Subject(); movieResults: ISearchMovieResult[]; result: IRequestEngineResult; - searchApplied = false; + searchApplied = false; constructor(private searchService: SearchService, private requestService: RequestService, private notificationService: NotificationService) { this.searchChanged .debounceTime(600) // Wait Xms afterthe last event before emitting last event .distinctUntilChanged() // only emit if value is different from previous value + .takeUntil(this.subscriptions) .subscribe(x => { this.searchText = x as string; if (this.searchText === "") { this.clearResults(); return; } - this.searchService.searchMovie(this.searchText).subscribe(x => { - this.movieResults = x; - this.searchApplied = true; - // Now let's load some exta info including IMDBId - // This way the search is fast at displaying results. - this.getExtaInfo(); - }); + this.searchService.searchMovie(this.searchText) + .takeUntil(this.subscriptions) + .subscribe(x => { + this.movieResults = x; + this.searchApplied = true; + // Now let's load some exta info including IMDBId + // This way the search is fast at displaying results. + this.getExtaInfo(); + }); }); } @@ -59,49 +64,61 @@ export class MovieSearchComponent implements OnInit { request(searchResult: ISearchMovieResult) { searchResult.requested = true; - this.requestService.requestMovie(searchResult).subscribe(x => { - this.result = x; + this.requestService.requestMovie(searchResult) + .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`); - } else { - this.notificationService.warning("Request Added", this.result.message); - } - }); + if (this.result.requestAdded) { + this.notificationService.success("Request Added", + `Request for ${searchResult.title} has been added successfully`); + } else { + this.notificationService.warning("Request Added", this.result.message); + } + }); } popularMovies() { this.clearResults(); - this.searchService.popularMovies().subscribe(x => { - this.movieResults = x; - this.getExtaInfo(); - }); + this.searchService.popularMovies() + .takeUntil(this.subscriptions) + .subscribe(x => { + this.movieResults = x; + this.getExtaInfo(); + }); } nowPlayingMovies() { this.clearResults(); - this.searchService.nowPlayingMovies().subscribe(x => { - this.movieResults = x; - this.getExtaInfo(); - }); + this.searchService.nowPlayingMovies() + .takeUntil(this.subscriptions) + .subscribe(x => { + this.movieResults = x; + this.getExtaInfo(); + }); } topRatedMovies() { this.clearResults(); - this.searchService.topRatedMovies().subscribe(x => { - this.movieResults = x; - this.getExtaInfo(); - }); + this.searchService.topRatedMovies() + .takeUntil(this.subscriptions) + .subscribe(x => { + this.movieResults = x; + this.getExtaInfo(); + }); } upcomingMovies() { this.clearResults(); - this.searchService.upcomignMovies().subscribe(x => { - this.movieResults = x; - this.getExtaInfo(); - }); + this.searchService.upcomignMovies() + .takeUntil(this.subscriptions) + .subscribe(x => { + this.movieResults = x; + this.getExtaInfo(); + }); } private getExtaInfo() { - this.searchService.extraInfo(this.movieResults).subscribe(m => this.movieResults = m); + this.searchService.extraInfo(this.movieResults) + .takeUntil(this.subscriptions) + .subscribe(m => this.movieResults = m); } private clearResults() { @@ -109,4 +126,9 @@ export class MovieSearchComponent implements OnInit { this.searchApplied = false; } + ngOnDestroy(): void { + this.subscriptions.next(); + this.subscriptions.complete(); + } + } \ No newline at end of file diff --git a/Ombi/Ombi/wwwroot/app/search/tvsearch.component.html b/Ombi/Ombi/wwwroot/app/search/tvsearch.component.html index 5ef77290e..534580794 100644 --- a/Ombi/Ombi/wwwroot/app/search/tvsearch.component.html +++ b/Ombi/Ombi/wwwroot/app/search/tvsearch.component.html @@ -48,7 +48,7 @@ - {{result.status}} + {{result.status}} Air Date: {{result.firstAired}} @@ -95,13 +95,13 @@
-
+ - {{/if_eq}} - {{#if available}} - {{#if url}} + + + + -->
diff --git a/Ombi/Ombi/wwwroot/app/search/tvsearch.component.ts b/Ombi/Ombi/wwwroot/app/search/tvsearch.component.ts index 7913a390e..c7e162a09 100644 --- a/Ombi/Ombi/wwwroot/app/search/tvsearch.component.ts +++ b/Ombi/Ombi/wwwroot/app/search/tvsearch.component.ts @@ -1,8 +1,9 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { Subject } from 'rxjs/Subject'; import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/distinctUntilChanged'; import 'rxjs/add/operator/map'; +import "rxjs/add/operator/takeUntil"; import { SearchService } from '../services/search.service'; import { RequestService } from '../services/request.service'; @@ -16,8 +17,9 @@ import { IRequestEngineResult } from '../interfaces/IRequestEngineResult'; moduleId: module.id, templateUrl: './tvsearch.component.html', }) -export class TvSearchComponent implements OnInit { +export class TvSearchComponent implements OnInit, OnDestroy { + private subscriptions = new Subject(); searchText: string; searchChanged = new Subject(); tvResults: ISearchTvResult[]; @@ -28,16 +30,19 @@ export class TvSearchComponent implements OnInit { this.searchChanged .debounceTime(600) // Wait Xms afterthe last event before emitting last event .distinctUntilChanged() // only emit if value is different from previous value + .takeUntil(this.subscriptions) .subscribe(x => { this.searchText = x as string; if (this.searchText === "") { this.clearResults(); return; } - this.searchService.searchTv(this.searchText).subscribe(x => { - this.tvResults = x; - this.searchApplied = true; - }); + this.searchService.searchTv(this.searchText) + .takeUntil(this.subscriptions) + .subscribe(x => { + this.tvResults = x; + this.searchApplied = true; + }); }); } @@ -57,50 +62,81 @@ export class TvSearchComponent implements OnInit { popularShows() { this.clearResults(); - this.searchService.popularTv().subscribe(x => { - this.tvResults = x; - }); + this.searchService.popularTv() + .takeUntil(this.subscriptions) + .subscribe(x => { + this.tvResults = x; + }); } trendingShows() { this.clearResults(); - this.searchService.trendingTv().subscribe(x => { - this.tvResults = x; - }); + this.searchService.trendingTv() + .takeUntil(this.subscriptions) + .subscribe(x => { + this.tvResults = x; + }); } mostWatchedShows() { this.clearResults(); - this.searchService.mostWatchedTv().subscribe(x => { - this.tvResults = x; - }); + this.searchService.mostWatchedTv() + .takeUntil(this.subscriptions) + .subscribe(x => { + this.tvResults = x; + }); } anticipatedShows() { this.clearResults(); - this.searchService.anticiplatedTv().subscribe(x => { - this.tvResults = x; - }); + this.searchService.anticiplatedTv() + .takeUntil(this.subscriptions) + .subscribe(x => { + this.tvResults = x; + }); } request(searchResult: ISearchTvResult) { searchResult.requested = true; - this.requestService.requestTv(searchResult).subscribe(x => { - this.result = x; - - if (this.result.requestAdded) { - this.notificationService.success("Request Added", - `Request for ${searchResult.seriesName} has been added successfully`); - } else { - this.notificationService.warning("Request Added", this.result.message); - } - }); + this.requestService.requestTv(searchResult) + .takeUntil(this.subscriptions) + .subscribe(x => { + this.result = x; + + if (this.result.requestAdded) { + this.notificationService.success("Request Added", + `Request for ${searchResult.seriesName} has been added successfully`); + } else { + this.notificationService.warning("Request Added", this.result.message); + } + }); + } + + + allSeasons(searchResult: ISearchTvResult) { + searchResult.requestAll = true; + this.request(searchResult); + } + + firstSeason(searchResult: ISearchTvResult) { + searchResult.firstSeason = true; + this.request(searchResult); } - + + latestSeason(searchResult: ISearchTvResult) { + searchResult.latestSeason = true; + this.request(searchResult); + } + private clearResults() { this.tvResults = []; this.searchApplied = false; } + ngOnDestroy(): void { + this.subscriptions.next(); + this.subscriptions.complete(); + } + } \ No newline at end of file diff --git a/Ombi/Ombi/wwwroot/app/usermanagement/usermanagement.component.html b/Ombi/Ombi/wwwroot/app/usermanagement/usermanagement.component.html index fb0392866..8afc22723 100644 --- a/Ombi/Ombi/wwwroot/app/usermanagement/usermanagement.component.html +++ b/Ombi/Ombi/wwwroot/app/usermanagement/usermanagement.component.html @@ -127,7 +127,7 @@ -