Damn son. So many changes... Fixed alot of stuff around tv episodes with the new DB model #865

This commit is contained in:
tidusjar 2017-06-28 23:15:01 +01:00
parent 1a7f81b16c
commit 0875b5f665
40 changed files with 340 additions and 874 deletions

View file

@ -1,110 +1,110 @@
using System.Collections.Generic; //using System.Collections.Generic;
using System.Threading.Tasks; //using System.Threading.Tasks;
using Moq; //using Moq;
using Ombi.Core.Models.Requests; //using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Requests.Movie; //using Ombi.Core.Models.Requests.Movie;
using Ombi.Core.Models.Requests.Tv; //using Ombi.Core.Models.Requests.Tv;
using Ombi.Core.Models.Search; //using Ombi.Core.Models.Search;
using Ombi.Core.Requests.Models; //using Ombi.Core.Requests.Models;
using Ombi.Core.Rule.Rules.Search; //using Ombi.Core.Rule.Rules.Search;
using Xunit; //using Xunit;
namespace Ombi.Core.Tests.Rule.Search //namespace Ombi.Core.Tests.Rule.Search
{ //{
public class ExistignRequestRuleTests // public class ExistignRequestRuleTests
{ // {
public ExistignRequestRuleTests() // public ExistignRequestRuleTests()
{ // {
MovieMock = new Mock<IRequestService<MovieRequestModel>>(); // MovieMock = new Mock<IRequestService<MovieRequestModel>>();
TvMock = new Mock<IRequestService<TvRequestModel>>(); // TvMock = new Mock<IRequestService<TvRequestModel>>();
Rule = new ExistingRequestRule(MovieMock.Object, TvMock.Object); // Rule = new ExistingRequestRule(MovieMock.Object, TvMock.Object);
} // }
private ExistingRequestRule Rule { get; } // private ExistingRequestRule Rule { get; }
private Mock<IRequestService<MovieRequestModel>> MovieMock { get; } // private Mock<IRequestService<MovieRequestModel>> MovieMock { get; }
private Mock<IRequestService<TvRequestModel>> TvMock { get; } // private Mock<IRequestService<TvRequestModel>> TvMock { get; }
[Fact] // [Fact]
public async Task ShouldBe_Requested_WhenExisitngMovie() // public async Task ShouldBe_Requested_WhenExisitngMovie()
{ // {
var list = new List<MovieRequestModel>{new MovieRequestModel // var list = new List<MovieRequestModel>{new MovieRequestModel
{ // {
ProviderId = 123, // ProviderId = 123,
Approved = true // Approved = true
}}; // }};
MovieMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list); // MovieMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list);
var search = new SearchMovieViewModel // var search = new SearchMovieViewModel
{ // {
Id = 123, // Id = 123,
}; // };
var result = await Rule.Execute(search); // var result = await Rule.Execute(search);
Assert.True(result.Success); // Assert.True(result.Success);
Assert.Equal(search.Approved, true); // Assert.Equal(search.Approved, true);
} // }
[Fact] // [Fact]
public async Task ShouldBe_NotRequested_WhenNewMovie() // public async Task ShouldBe_NotRequested_WhenNewMovie()
{ // {
var list = new List<MovieRequestModel>{new MovieRequestModel // var list = new List<MovieRequestModel>{new MovieRequestModel
{ // {
ProviderId = 123, // ProviderId = 123,
Approved = true // Approved = true
}}; // }};
MovieMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list); // MovieMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list);
var search = new SearchMovieViewModel // var search = new SearchMovieViewModel
{ // {
Id = 999, // Id = 999,
}; // };
var result = await Rule.Execute(search); // var result = await Rule.Execute(search);
Assert.True(result.Success); // Assert.True(result.Success);
Assert.Equal(search.Approved, false); // Assert.Equal(search.Approved, false);
} // }
[Fact] // [Fact]
public async Task ShouldBe_Requested_WhenExisitngTv() // public async Task ShouldBe_Requested_WhenExisitngTv()
{ // {
var list = new List<TvRequestModel>{new TvRequestModel // var list = new List<TvRequestModel>{new TvRequestModel
{ // {
ProviderId = 123, // ProviderId = 123,
Approved = true // Approved = true
}}; // }};
TvMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list); // TvMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list);
var search = new SearchTvShowViewModel // var search = new SearchTvShowViewModel
{ // {
Id = 123, // Id = 123,
}; // };
var result = await Rule.Execute(search); // var result = await Rule.Execute(search);
Assert.True(result.Success); // Assert.True(result.Success);
Assert.Equal(search.Approved, true); // Assert.Equal(search.Approved, true);
} // }
[Fact] // [Fact]
public async Task ShouldBe_NotRequested_WhenNewTv() // public async Task ShouldBe_NotRequested_WhenNewTv()
{ // {
var list = new List<TvRequestModel>{new TvRequestModel // var list = new List<TvRequestModel>{new TvRequestModel
{ // {
ProviderId = 123, // ProviderId = 123,
Approved = true // Approved = true
}}; // }};
TvMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list); // TvMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list);
var search = new SearchTvShowViewModel() // var search = new SearchTvShowViewModel()
{ // {
Id = 999, // Id = 999,
}; // };
var result = await Rule.Execute(search); // var result = await Rule.Execute(search);
Assert.True(result.Success); // Assert.True(result.Success);
Assert.Equal(search.Approved, false); // Assert.Equal(search.Approved, false);
} // }
} // }
} //}

View file

@ -1,19 +1,11 @@
using System; using Ombi.Core.Claims;
using Ombi.Core.Claims;
using Ombi.Core.Models.Requests;
using Ombi.Core.Rule; using Ombi.Core.Rule;
using Ombi.Core.Rules; using Ombi.Core.Rules;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Ombi.Core.Models.Requests.Movie;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Core.Notifications;
using Ombi.Helpers;
using Ombi.Notifications.Models;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
namespace Ombi.Core.Engine.Interfaces namespace Ombi.Core.Engine.Interfaces

View file

@ -1,7 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Requests.Tv;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;

View file

@ -1,10 +1,8 @@
using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Requests.Movie;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Core.Rules; using Ombi.Core.Rules;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Notifications;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View file

@ -1,16 +1,12 @@
using AutoMapper; using AutoMapper;
using Hangfire;
using Ombi.Api.TvMaze; using Ombi.Api.TvMaze;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Core.Rules; using Ombi.Core.Rules;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Notifications;
using Ombi.Notifications.Models;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Security.Principal; using System.Security.Principal;
@ -18,7 +14,6 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Ombi.Core.Engine.Interfaces; using Ombi.Core.Engine.Interfaces;
using Ombi.Core.IdentityResolver; using Ombi.Core.IdentityResolver;
using Ombi.Core.Models.Requests.Tv;
using Ombi.Core.Rule; using Ombi.Core.Rule;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository.Requests; using Ombi.Store.Repository.Requests;
@ -50,7 +45,7 @@ namespace Ombi.Core.Engine
// For some reason the poster path is always http // For some reason the poster path is always http
var posterPath = showInfo.image?.medium.Replace("http:", "https:"); var posterPath = showInfo.image?.medium.Replace("http:", "https:");
var tvRequests = new List<SeasonRequestModel>(); var tvRequests = new List<SeasonRequests>();
// Only have the TV requests we actually requested and not everything // Only have the TV requests we actually requested and not everything
foreach (var season in tv.SeasonRequests) foreach (var season in tv.SeasonRequests)
{ {
@ -84,7 +79,44 @@ namespace Ombi.Core.Engine
SeasonRequests = new List<SeasonRequests>() SeasonRequests = new List<SeasonRequests>()
}; };
if (tv.LatestSeason) if (tv.RequestAll)
{
var episodes = await TvApi.EpisodeLookup(showInfo.id);
var seasonRequests = new List<SeasonRequests>();
foreach (var ep in episodes)
{
var episodesRequests = new List<EpisodeRequests>();
var season = childRequest.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == ep.season);
if (season == null)
{
childRequest.SeasonRequests.Add(new SeasonRequests
{
Episodes = new List<EpisodeRequests>{
new EpisodeRequests
{
EpisodeNumber = ep.number,
AirDate = DateTime.Parse(ep.airdate),
Title = ep.name,
Url = ep.url
}
},
SeasonNumber = ep.season,
});
}
else
{
season.Episodes.Add(new EpisodeRequests
{
EpisodeNumber = ep.number,
AirDate = DateTime.Parse(ep.airdate),
Title = ep.name,
Url = ep.url
});
}
}
}
else if (tv.LatestSeason)
{ {
var episodes = await TvApi.EpisodeLookup(showInfo.id); var episodes = await TvApi.EpisodeLookup(showInfo.id);
var latest = episodes.OrderBy(x => x.season).FirstOrDefault(); var latest = episodes.OrderBy(x => x.season).FirstOrDefault();
@ -105,8 +137,7 @@ namespace Ombi.Core.Engine
SeasonNumber = latest.season, SeasonNumber = latest.season,
}); });
} }
else if (tv.FirstSeason)
if (tv.FirstSeason)
{ {
var episodes = await TvApi.EpisodeLookup(showInfo.id); var episodes = await TvApi.EpisodeLookup(showInfo.id);
var first = episodes.OrderByDescending(x => x.season).FirstOrDefault(); var first = episodes.OrderByDescending(x => x.season).FirstOrDefault();
@ -130,7 +161,12 @@ namespace Ombi.Core.Engine
SeasonNumber = first.season, SeasonNumber = first.season,
}); });
} }
else
{
// It's a custom request
childRequest.SeasonRequests = tvRequests;
}
var ruleResults = await RunRequestRules(childRequest); var ruleResults = await RunRequestRules(childRequest);
var results = ruleResults as RuleResult[] ?? ruleResults.ToArray(); var results = ruleResults as RuleResult[] ?? ruleResults.ToArray();
if (results.Any(x => !x.Success)) if (results.Any(x => !x.Success))
@ -144,6 +180,35 @@ namespace Ombi.Core.Engine
var existingRequest = await TvRepository.Get().FirstOrDefaultAsync(x => x.TvDbId == tv.Id); var existingRequest = await TvRepository.Get().FirstOrDefaultAsync(x => x.TvDbId == tv.Id);
if (existingRequest != null) if (existingRequest != null)
{ {
// Remove requests we already have, we just want new ones
var existingSeasons = existingRequest.ChildRequests.Select(x => x.SeasonRequests);
foreach (var existingSeason in existingRequest.ChildRequests)
foreach (var existing in existingSeason.SeasonRequests)
{
var newChild = childRequest.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == existing.SeasonNumber);
if (newChild != null)
{
// We have some requests in this season...
// Let's find the episodes.
foreach (var existingEp in existing.Episodes)
{
var duplicateEpisode = newChild.Episodes.FirstOrDefault(x => x.EpisodeNumber == existingEp.EpisodeNumber);
if (duplicateEpisode != null)
{
// Remove it.
newChild.Episodes.Remove(duplicateEpisode);
}
}
if (!newChild.Episodes.Any())
{
// We may have removed all episodes
childRequest.SeasonRequests.Remove(newChild);
}
}
}
// Remove the ID since this is a new child
childRequest.Id = 0;
return await AddExistingRequest(childRequest, existingRequest); return await AddExistingRequest(childRequest, existingRequest);
} }
// This is a new request // This is a new request
@ -190,7 +255,7 @@ namespace Ombi.Core.Engine
results = Mapper.Map<TvRequests>(request); results = Mapper.Map<TvRequests>(request);
// TODO need to check if we need to approve any child requests since they may have updated // TODO need to check if we need to approve any child requests since they may have updated
await TvRepository.Update(results); await TvRepository.Update(results);
return results; return results;
} }
@ -215,47 +280,6 @@ namespace Ombi.Core.Engine
return await AfterRequest(newRequest); return await AfterRequest(newRequest);
} }
private IEnumerable<SeasonRequestModel> GetListDifferences(List<SeasonRequestModel> existing,
List<SeasonRequestModel> request)
{
var requestsToRemove = new List<SeasonRequestModel>();
foreach (var r in request)
{
// Do we have an existing season?
var existingSeason = existing.FirstOrDefault(x => x.SeasonNumber == r.SeasonNumber);
if (existingSeason == null)
{
continue;
}
// Compare the episodes
for (var i = r.Episodes.Count - 1; i >= 0; i--)
{
var existingEpisode = existingSeason.Episodes.FirstOrDefault(x => x.EpisodeNumber == r.Episodes[i].EpisodeNumber);
if (existingEpisode == null)
{
// we are fine, we have not yet requested this
}
else
{
// We already have this request
r.Episodes.RemoveAt(i);
}
}
if (!r.Episodes.Any())
{
requestsToRemove.Add(r);
}
}
foreach (var remove in requestsToRemove)
{
request.Remove(remove);
}
return request;
}
private async Task<RequestEngineResult> AddRequest(TvRequests model) private async Task<RequestEngineResult> AddRequest(TvRequests model)
{ {
await TvRepository.Add(model); await TvRepository.Add(model);

View file

@ -15,8 +15,8 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Core.Models.Requests.Tv;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository.Requests;
namespace Ombi.Core.Engine namespace Ombi.Core.Engine
{ {
@ -64,29 +64,32 @@ namespace Ombi.Core.Engine
var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season); var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season);
if (season == null) if (season == null)
{ {
var newSeason = new SeasonRequestModel var newSeason = new SeasonRequests
{ {
SeasonNumber = e.season, SeasonNumber = e.season,
Episodes = new List<EpisodeRequests>()
}; };
newSeason.Episodes.Add(new EpisodesRequested newSeason.Episodes.Add(new EpisodeRequests
{
Url = e.url,
Title = e.name,
AirDate = DateTime.Parse(e.airstamp),
EpisodeNumber = e.number,
});
mapped.SeasonRequests.Add(newSeason);
}
else
{
// We already have the season, so just add the episode
season.Episodes.Add(new EpisodeRequests
{ {
Url = e.url, Url = e.url,
Title = e.name, Title = e.name,
AirDate = DateTime.Parse(e.airstamp), AirDate = DateTime.Parse(e.airstamp),
EpisodeNumber = e.number, EpisodeNumber = e.number,
}); });
mapped.SeasonRequests.Add(newSeason);
} }
//else
//{
// // Find the episode
// var ep = episodes.FirstOrDefault(x => x.number == e.number);
// ep.Url = e.url;
// ep.Title = e.name;
// ep.AirDate = DateTime.Parse(e.airstamp);
// ep.EpisodeNumber = e.number;
//}
} }
var existingRequests = await GetTvRequests(); var existingRequests = await GetTvRequests();

View file

@ -1,5 +1,4 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Core.Models.Requests.Movie;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
namespace Ombi.Core namespace Ombi.Core

View file

@ -1,40 +0,0 @@
using Newtonsoft.Json;
using Ombi.Store.Entities;
using System;
namespace Ombi.Core.Models.Requests
{
public class BaseRequestModel : Entity
{
public int ProviderId { get; set; }
public string Overview { get; set; }
public string Title { get; set; }
public string PosterPath { get; set; }
public DateTime ReleaseDate { get; set; }
public RequestType Type { get; set; }
public string Status { get; set; }
public bool Approved { get; set; }
public bool Admin { get; set; }
public DateTime RequestedDate { get; set; }
public bool Available { get; set; }
public IssueState Issues { get; set; }
public string OtherMessage { get; set; }
public string AdminNote { get; set; }
public string RequestedUser { get; set; }
public int IssueId { get; set; }
public bool Denied { get; set; }
public string DeniedReason { get; set; }
[JsonIgnore]
public bool Released => DateTime.UtcNow > ReleaseDate;
[JsonIgnore]
public bool CanApprove => !Approved && !Available;
public bool UserHasRequested(string username)
{
return RequestedUser.Equals(username, StringComparison.OrdinalIgnoreCase);
}
}
}

View file

@ -1,42 +0,0 @@
using Ombi.Core.Models.Requests;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ombi.Core.Requests.Models
{
public interface IRequestService<T> where T : BaseRequestModel
{
int AddRequest(T model);
Task<int> AddRequestAsync(T model);
void BatchDelete(IEnumerable<T> model);
void BatchUpdate(IEnumerable<T> model);
T CheckRequest(int providerId);
Task<T> CheckRequestAsync(int providerId);
void DeleteRequest(T request);
Task DeleteRequestAsync(int request);
Task DeleteRequestAsync(T request);
T Get(int id);
IEnumerable<T> GetAll();
Task<IEnumerable<T>> GetAllAsync();
Task<IEnumerable<T>> GetAllAsync(int count, int position);
Task<T> GetAsync(int id);
T UpdateRequest(T model);
IQueryable<T> GetAllQueryable();
}
}

View file

@ -0,0 +1,12 @@
namespace Ombi.Core.Models.Requests
{
public enum IssueState
{
None = 99,
WrongAudio = 0,
NoSubtitles = 1,
WrongContent = 2,
PlaybackIssues = 3,
Other = 4 // Provide a message
}
}

View file

@ -1,212 +0,0 @@
using Ombi.Core.Requests.Models;
using Ombi.Helpers;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Ombi.Core.Models.Requests.Tv;
namespace Ombi.Core.Models.Requests
{
public class JsonRequestService<T> : IRequestService<T> where T : BaseRequestModel
{
public JsonRequestService(IRequestRepository repo)
{
Repo = repo;
RequestType = typeof(T) == typeof(TvRequestModel) ? RequestType.TvShow : RequestType.Movie;
}
private RequestType RequestType { get; }
private IRequestRepository Repo { get; }
public int AddRequest(T model)
{
var entity = new RequestBlobs
{
Type = model.Type,
Content = ByteConverterHelper.ReturnBytes(model),
ProviderId = model.ProviderId
};
var id = Repo.Insert(entity);
return id.Id;
}
public async Task<int> AddRequestAsync(T model)
{
var entity = new RequestBlobs
{
Type = model.Type,
Content = ByteConverterHelper.ReturnBytes(model),
ProviderId = model.ProviderId
};
var id = await Repo.InsertAsync(entity).ConfigureAwait(false);
return id.Id;
}
public T CheckRequest(int providerId)
{
var blobs = Repo.GetAll();
var blob = blobs.FirstOrDefault(x => x.ProviderId == providerId && x.Type == RequestType);
if (blob == null)
return null;
var model = ByteConverterHelper.ReturnObject<T>(blob.Content);
model.Id = blob.Id;
return model;
}
public async Task<T> CheckRequestAsync(int providerId)
{
var blobs = await Repo.GetAllAsync().ConfigureAwait(false);
var blob = blobs.FirstOrDefault(x => x.ProviderId == providerId && x.Type == RequestType);
if (blob == null)
return null;
var model = ByteConverterHelper.ReturnObject<T>(blob.Content);
model.Id = blob.Id;
return model;
}
public void DeleteRequest(T request)
{
var blob = Repo.Get(request.Id);
Repo.Delete(blob);
}
public async Task DeleteRequestAsync(T request)
{
var blob = await Repo.GetAsync(request.Id).ConfigureAwait(false);
Repo.Delete(blob);
}
public async Task DeleteRequestAsync(int request)
{
var blob = await Repo.GetAsync(request).ConfigureAwait(false);
Repo.Delete(blob);
}
public T UpdateRequest(T model)
{
var b = Repo.Get(model.Id);
b.Content = ByteConverterHelper.ReturnBytes(model);
var blob = Repo.Update(b);
return model;
}
public T Get(int id)
{
var blob = Repo.Get(id);
if (blob == null)
return default(T);
var model = ByteConverterHelper.ReturnObject<T>(blob.Content);
model.Id =
blob
.Id; // They should always be the same, but for somereason a user didn't have it in the db https://github.com/tidusjar/Ombi/issues/862#issuecomment-269743847
return model;
}
public async Task<T> GetAsync(int id)
{
var blob = await Repo.GetAsync(id).ConfigureAwait(false);
if (blob == null)
return default(T);
var model = ByteConverterHelper.ReturnObject<T>(blob.Content);
model.Id = blob.Id;
return model;
}
public IEnumerable<T> GetAll()
{
var blobs = Repo.GetAll().Where(x => x.Type == RequestType).ToList();
var retVal = new List<T>();
foreach (var b in blobs)
{
if (b == null)
continue;
var model = ByteConverterHelper.ReturnObject<T>(b.Content);
model.Id = b.Id;
retVal.Add(model);
}
return retVal;
}
public IQueryable<T> GetAllQueryable()
{
var retVal = new List<T>();
var blobs = Repo.GetAllQueryable();
foreach (var b in blobs)
{
if (b == null)
continue;
var model = ByteConverterHelper.ReturnObject<T>(b.Content);
model.Id = b.Id;
retVal.Add(model);
}
return retVal.AsQueryable();
}
public async Task<IEnumerable<T>> GetAllAsync()
{
var blobs = await Repo.GetAllAsync().ConfigureAwait(false);
var retVal = new List<T>();
foreach (var b in blobs.Where(x => x.Type == RequestType))
{
if (b == null)
continue;
var model = ByteConverterHelper.ReturnObject<T>(b.Content);
model.Id = b.Id;
retVal.Add(model);
}
return retVal;
}
public async Task<IEnumerable<T>> GetAllAsync(int count, int position)
{
var blobs = await Repo.GetAllAsync().ConfigureAwait(false);
var retVal = new List<T>();
foreach (var b in blobs.Where(x => x.Type == RequestType).Skip(position).Take(count))
{
if (b == null)
continue;
var model = ByteConverterHelper.ReturnObject<T>(b.Content);
model.Id = b.Id;
retVal.Add(model);
}
return retVal;
}
public void BatchUpdate(IEnumerable<T> model)
{
var entities = model
.Select(m => new RequestBlobs
{
Type = m.Type,
Content = ByteConverterHelper.ReturnBytes(m),
ProviderId = m.ProviderId,
Id = m.Id
})
.ToList();
Repo.UpdateAll(entities);
}
public void BatchDelete(IEnumerable<T> model)
{
var entities = model
.Select(m => new RequestBlobs
{
Type = m.Type,
Content = ByteConverterHelper.ReturnBytes(m),
ProviderId = m.ProviderId,
Id = m.Id
})
.ToList();
Repo.DeleteAll(entities);
}
}
}

View file

@ -1,7 +0,0 @@
namespace Ombi.Core.Models.Requests.Movie
{
public class MovieRequestModel : BaseRequestModel
{
public string ImdbId { get; set; }
}
}

View file

@ -1,61 +0,0 @@
using Ombi.Store.Entities;
using System;
using System.Collections.Generic;
namespace Ombi.Core.Models.Requests
{
public enum IssueState
{
None = 99,
WrongAudio = 0,
NoSubtitles = 1,
WrongContent = 2,
PlaybackIssues = 3,
Other = 4 // Provide a message
}
public class EpisodesModel : IEquatable<EpisodesModel>
{
public int SeasonNumber { get; set; }
public int EpisodeNumber { get; set; }
public bool Equals(EpisodesModel other)
{
// Check whether the compared object is null.
if (ReferenceEquals(other, null)) return false;
//Check whether the compared object references the same data.
if (ReferenceEquals(this, other)) return true;
//Check whether the properties are equal.
return SeasonNumber.Equals(other.SeasonNumber) && EpisodeNumber.Equals(other.EpisodeNumber);
}
public override int GetHashCode()
{
var hashSeason = SeasonNumber.GetHashCode();
var hashEp = EpisodeNumber.GetHashCode();
//Calculate the hash code.
return hashSeason + hashEp;
}
}
public class SeasonRequestModel
{
public int SeasonNumber { get; set; }
public List<EpisodesRequested> Episodes { get; set; } = new List<EpisodesRequested>();
}
public class EpisodesRequested
{
public int EpisodeNumber { get; set; }
public string Title { get; set; }
public DateTime AirDate { get; set; }
public string Url { get; set; }
public bool Requested { get; set; }
public string Status { get; set; }
public bool Available { get; set; }
public bool Approved { get; set; }
}
}

View file

@ -1,33 +0,0 @@
using Ombi.Store.Entities;
using System;
namespace Ombi.Core.Models.Requests
{
public class RequestViewModel
{
public int Id { get; set; }
public int ProviderId { get; set; }
public string ImdbId { get; set; }
public string Overview { get; set; }
public string Title { get; set; }
public string PosterPath { get; set; }
public DateTime ReleaseDate { get; set; }
public bool Released { get; set; }
public RequestType Type { get; set; }
public string Status { get; set; }
public bool Approved { get; set; }
public string[] RequestedUsers { get; set; }
public DateTime RequestedDate { get; set; }
public string ReleaseYear { get; set; }
public bool Available { get; set; }
public bool Admin { get; set; }
public int IssueId { get; set; }
public QualityModel[] Qualities { get; set; }
public EpisodesModel[] Episodes { get; set; }
public bool Denied { get; set; }
public string DeniedReason { get; set; }
public RootFolderModel[] RootFolders { get; set; }
public bool HasRootFolders { get; set; }
public string CurrentRootPath { get; set; }
}
}

View file

@ -1,31 +0,0 @@
using System.Collections.Generic;
namespace Ombi.Core.Models.Requests.Tv
{
public class TvRequestModel : BaseRequestModel
{
public TvRequestModel()
{
ChildRequests = new List<ChildTvRequest>();
}
public string ImdbId { get; set; }
public string TvDbId { get; set; }
public List<ChildTvRequest> ChildRequests { get; set; }
/// <summary>
/// For TV Shows with a custom root folder
/// </summary>
/// <value>
/// The root folder selected.
/// </value>
public int RootFolderSelected { get; set; }
}
public class ChildTvRequest : BaseRequestModel
{
public bool RequestAll { get; set; }
public List<SeasonRequestModel> SeasonRequests { get; set; } = new List<SeasonRequestModel>();
}
}

View file

@ -1,4 +1,5 @@
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Store.Repository.Requests;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ombi.Core.Models.Search namespace Ombi.Core.Models.Search
@ -39,7 +40,7 @@ namespace Ombi.Core.Models.Search
/// </value> /// </value>
public string Homepage { get; set; } public string Homepage { get; set; }
public List<SeasonRequestModel> SeasonRequests { get; set; } = new List<SeasonRequestModel>(); public List<SeasonRequests> SeasonRequests { get; set; } = new List<SeasonRequests>();
/// <summary> /// <summary>
/// If we are requesting the entire series /// If we are requesting the entire series

View file

@ -1,10 +1,8 @@
using Ombi.Core.Models.Requests.Movie; using Ombi.Core.Settings;
using Ombi.Core.Settings;
using Ombi.Settings.Settings.Models.External; using Ombi.Settings.Settings.Models.External;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Api.Radarr; using Ombi.Api.Radarr;
using Ombi.Core.Models.Requests;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;

View file

@ -30,4 +30,9 @@
<ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.Api.TheMovieDb.csproj" /> <ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.Api.TheMovieDb.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Models\Requests\Movie\" />
<Folder Include="Models\Requests\Tv\" />
</ItemGroup>
</Project> </Project>

View file

@ -1,11 +1,7 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Requests.Movie;
using Ombi.Core.Models.Requests.Tv;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Core.Requests.Models;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests; using Ombi.Store.Repository.Requests;

View file

@ -17,7 +17,6 @@ using Ombi.Core.Engine.Interfaces;
using Ombi.Core.IdentityResolver; using Ombi.Core.IdentityResolver;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Notifications; using Ombi.Core.Notifications;
using Ombi.Core.Requests.Models;
using Ombi.Core.Rule; using Ombi.Core.Rule;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Notifications; using Ombi.Notifications;
@ -75,7 +74,6 @@ namespace Ombi.DependencyInjection
services.AddEntityFrameworkSqlite().AddDbContext<OmbiContext>(); services.AddEntityFrameworkSqlite().AddDbContext<OmbiContext>();
services.AddScoped<IOmbiContext, OmbiContext>(); services.AddScoped<IOmbiContext, OmbiContext>();
services.AddTransient<IRequestRepository, RequestJsonRepository>();
services.AddTransient<ISettingsRepository, SettingsJsonRepository>(); services.AddTransient<ISettingsRepository, SettingsJsonRepository>();
services.AddTransient<IUserRepository, UserRepository>(); services.AddTransient<IUserRepository, UserRepository>();
services.AddTransient<ISettingsResolver, SettingsResolver>(); services.AddTransient<ISettingsResolver, SettingsResolver>();
@ -89,7 +87,6 @@ namespace Ombi.DependencyInjection
public static void RegisterServices(this IServiceCollection services) public static void RegisterServices(this IServiceCollection services)
{ {
services.AddTransient<IRequestServiceMain, RequestService>(); services.AddTransient<IRequestServiceMain, RequestService>();
services.AddTransient(typeof(IRequestService<>), typeof(JsonRequestService<>));
services.AddSingleton<INotificationService, NotificationService>(); services.AddSingleton<INotificationService, NotificationService>();
services.AddTransient<INotificationHelper, NotificationHelper>(); services.AddTransient<INotificationHelper, NotificationHelper>();

View file

@ -7,6 +7,7 @@ using Ombi.Core.Models.Search;
using Ombi.Helpers; using Ombi.Helpers;
using TraktApiSharp.Objects.Get.Shows; using TraktApiSharp.Objects.Get.Shows;
using TraktApiSharp.Objects.Get.Shows.Common; using TraktApiSharp.Objects.Get.Shows.Common;
using Ombi.Store.Repository.Requests;
//using TraktApiSharp.Objects.Get.Shows; //using TraktApiSharp.Objects.Get.Shows;
//using TraktApiSharp.Objects.Get.Shows.Common; //using TraktApiSharp.Objects.Get.Shows.Common;
@ -51,23 +52,22 @@ namespace Ombi.Mapping.Profiles
CreateMap<TvMazeCustomSeason, SeasonRequestModel>() //CreateMap<TvMazeCustomSeason, SeasonRequests>()
.ConstructUsing(x => // .ConstructUsing(x =>
{ // {
var season = new SeasonRequestModel // var season = new SeasonRequests
{ // {
SeasonNumber = x.SeasonNumber // SeasonNumber = x.SeasonNumber
}; // };
foreach (var ep in x.EpisodeNumber) // foreach (var ep in x.EpisodeNumber)
{ // {
season.Episodes.Add(new EpisodesRequested // season.Episodes.Add(new EpisodeRequests
{ // {
EpisodeNumber = ep, // EpisodeNumber = ep,
// });
}); // }
} // return season;
return season; // });
});

View file

@ -13,7 +13,6 @@ namespace Ombi.Store.Context
{ {
int SaveChanges(); int SaveChanges();
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)); Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
DbSet<RequestBlobs> Requests { get; set; }
DbSet<GlobalSettings> Settings { get; set; } DbSet<GlobalSettings> Settings { get; set; }
DbSet<PlexContent> PlexContent { get; set; } DbSet<PlexContent> PlexContent { get; set; }
DbSet<RadarrCache> RadarrCache { get; set; } DbSet<RadarrCache> RadarrCache { get; set; }

View file

@ -34,8 +34,7 @@ namespace Ombi.Store.Context
// Add the notifcation templates // Add the notifcation templates
AddAllTemplates(); AddAllTemplates();
} }
public DbSet<RequestBlobs> Requests { get; set; }
public DbSet<GlobalSettings> Settings { get; set; } public DbSet<GlobalSettings> Settings { get; set; }
public DbSet<User> Users { get; set; } public DbSet<User> Users { get; set; }
public DbSet<PlexContent> PlexContent { get; set; } public DbSet<PlexContent> PlexContent { get; set; }

View file

@ -1,18 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Ombi.Store.Entities
{
[Table("RequestBlobs")]
public class RequestBlobs : Entity
{
public int ProviderId { get; set; }
public byte[] Content { get; set; }
public RequestType Type { get; set; }
}
public enum RequestType
{
Movie = 1,
TvShow = 2
}
}

View file

@ -1,15 +0,0 @@
using System;
namespace Ombi.Store.Entities
{
public class RequestHistory : Entity
{
public int UserId { get; set; }
public RequestType Type { get; set; }
public DateTime RequestedDate { get; set; }
public int RequestId { get; set; }
public virtual RequestBlobs Request { get; set; }
public virtual User User { get; set; }
}
}

View file

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Ombi.Store.Entities
{
public enum RequestType
{
TvShow,
Movie
}
}

View file

@ -24,8 +24,10 @@ namespace Ombi.Store.Repository.Requests
public DateTime AirDate { get; set; } public DateTime AirDate { get; set; }
public string Url { get; set; } public string Url { get; set; }
public bool Available { get; set; } public bool Available { get; set; }
public bool Approved { get; set; }
public bool Requested { get; set; }
public int SeasonId { get; set; } public int SeasonId { get; set; }
[ForeignKey(nameof(SeasonId))] [ForeignKey(nameof(SeasonId))]
public SeasonRequests Season { get; set; } public SeasonRequests Season { get; set; }

View file

@ -1,22 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Ombi.Store.Entities;
namespace Ombi.Store.Repository
{
public interface IRequestRepository
{
void Delete(RequestBlobs entity);
void DeleteAll(IEnumerable<RequestBlobs> entity);
RequestBlobs Get(int id);
IEnumerable<RequestBlobs> GetAll();
Task<IEnumerable<RequestBlobs>> GetAllAsync();
Task<RequestBlobs> GetAsync(int id);
RequestBlobs Insert(RequestBlobs entity);
Task<RequestBlobs> InsertAsync(RequestBlobs entity);
RequestBlobs Update(RequestBlobs entity);
void UpdateAll(IEnumerable<RequestBlobs> entity);
IQueryable<RequestBlobs> GetAllQueryable();
}
}

View file

@ -1,140 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Ombi.Store.Context;
using Ombi.Store.Entities;
namespace Ombi.Store.Repository
{
public class RequestJsonRepository : IRequestRepository
{
//private ICacheProvider Cache { get; }
public RequestJsonRepository(IOmbiContext ctx)
{
Db = ctx;
}
private IOmbiContext Db { get; }
public RequestBlobs Insert(RequestBlobs entity)
{
var id = Db.Requests.Add(entity);
Db.SaveChanges();
return id.Entity;
}
public async Task<RequestBlobs> InsertAsync(RequestBlobs entity)
{
var id = await Db.Requests.AddAsync(entity).ConfigureAwait(false);
await Db.SaveChangesAsync();
return id.Entity;
}
public IEnumerable<RequestBlobs> GetAll()
{
//var key = "GetAll";
//var item = Cache.GetOrSet(key, () =>
//{
var page = Db.Requests.ToList();
return page;
//}, 5);
//return item;
}
public async Task<IEnumerable<RequestBlobs>> GetAllAsync()
{
//var key = "GetAll";
//var item = await Cache.GetOrSetAsync(key, async () =>
//{
var page = await Db.Requests.ToListAsync().ConfigureAwait(false);
return page;
//}, 5);
//return item;
}
public RequestBlobs Get(int id)
{
//var key = "Get" + id;
//var item = Cache.GetOrSet(key, () =>
//{
var page = Db.Requests.Find(id);
return page;
//}, 5);
//return item;
}
public async Task<RequestBlobs> GetAsync(int id)
{
//var key = "Get" + id;
//var item = await Cache.GetOrSetAsync(key, async () =>
//{
var page = await Db.Requests.FindAsync(id).ConfigureAwait(false);
return page;
//}, 5);
//return item;
}
public void Delete(RequestBlobs entity)
{
//ResetCache();
Db.Requests.Remove(entity);
Db.SaveChanges();
}
public RequestBlobs Update(RequestBlobs entity)
{
try
{
Db.SaveChanges();
return entity;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
public void UpdateAll(IEnumerable<RequestBlobs> entity)
{
Db.Requests.UpdateRange(entity);
Db.SaveChanges();
}
public void DeleteAll(IEnumerable<RequestBlobs> entity)
{
Db.Requests.RemoveRange(entity);
Db.SaveChanges();
}
public IQueryable<RequestBlobs> GetAllQueryable()
{
return Db.Requests.AsQueryable();
}
}
}

View file

@ -167,6 +167,8 @@ CREATE TABLE IF NOT EXISTS EpisodeRequests (
Url VARCHAR(100) NOT NULL, Url VARCHAR(100) NOT NULL,
SeasonId INTEGER NOT NULL, SeasonId INTEGER NOT NULL,
Available INTEGER NOT NULL, Available INTEGER NOT NULL,
Requested INTEGER NOT NULL,
Approved INTEGER NOT NULL,
FOREIGN KEY (SeasonId) REFERENCES SeasonRequests(Id) FOREIGN KEY (SeasonId) REFERENCES SeasonRequests(Id)

View file

@ -138,5 +138,7 @@ export interface IEpisodesRequests {
airDate: Date, airDate: Date,
url: string, url: string,
available: boolean, available: boolean,
requested: boolean,
approved: boolean,
} }

View file

@ -8,7 +8,6 @@
userType: UserType, userType: UserType,
} }
export enum UserType { export enum UserType {
LocalUser = 1, LocalUser = 1,
PlexUser = 2, PlexUser = 2,

View file

@ -17,7 +17,7 @@
<div class="row"> <div class="row">
<div class="col-sm-2"> <div class="col-sm-2">
<img class="img-responsive" src="https://image.tmdb.org/t/p/w150/{{request.posterPath}}" alt="poster"> <img class="img-responsive poster" src="https://image.tmdb.org/t/p/w150/{{request.posterPath}}" alt="poster">
</div> </div>

View file

@ -17,7 +17,7 @@
<div class="row"> <div class="row">
<div class="col-sm-2"> <div class="col-sm-2">
<img class="img-responsive" src="{{request.posterPath}}" alt="poster"> <img class="img-responsive poster" src="{{request.posterPath}}" alt="poster">
</div> </div>
@ -187,52 +187,85 @@
<p-dialog *ngIf="showChildDialogue" id="dialogOverride" header="{{selectedSeason?.title}}" [(visible)]="showChildDialogue" [contentStyle]="{'overflow':'auto','max-height':'500px'}" [width]="768">
<div class="row" *ngFor="let child of selectedSeason.childRequests">
<div class="col-md-12">
<!--Child Requests-->
<div class="col-md-9">
<span class="col-md-12">Requested By: <b>{{child.requestedUser.username}}</b></span>
<div class="modal fade in" *ngIf="showChildDialogue" style="display: block;"> <!--<span class="col-md-12" *ngIf="child.requestAll">Requested All Seasons</span>-->
<div class="modal-dialog"> <!--Seasons-->
<div class="modal-content"> <span *ngIf="child.approved && !child.available" class="label label-info">Processing Request</span>
<div class="modal-header"> <span *ngIf="child.denied" class="label label-danger">Request Denied</span>
<button type="button" class="close" (click)="showChildDialogue=false">&times;</button> <span *ngIf="child.deniedReason" title="{{child.deniedReason}}"><i class="fa fa-info-circle"></i></span>
<h4 class="modal-title">{{selectedSeason?.title}}</h4> <span *ngIf="!child.approved && !child.availble && !child.denied" class="label label-warning">Pending Approval</span>
</div> <div class="col-md-12" *ngFor="let seasons of child.seasonRequests">
<div class="modal-body">
<div class="row" *ngFor="let child of selectedSeason.childRequests">
<div class="col-md-12">
<!--Child Requests-->
<div class="col-md-9">
<span class="col-md-12">Requested By: <b>{{child.requestedUser}}</b></span>
<!--<span class="col-md-12" *ngIf="child.requestAll">Requested All Seasons</span>-->
<!--Seasons-->
<span *ngIf="child.approved && !child.available" class="label label-info">Processing Request</span>
<span *ngIf="child.denied" class="label label-danger">Request Denied</span>
<span *ngIf="child.deniedReason" title="{{child.deniedReason}}"><i class="fa fa-info-circle"></i></span>
<span *ngIf="!child.approved && !child.availble && !child.denied" class="label label-warning">Pending Approval</span>
<div class="col-md-12" *ngFor="let seasons of child.seasonRequests">
<span>Season: {{seasons.seasonNumber}}</span> <span><b>Season: {{seasons.seasonNumber}}</b></span>
<span>Episodes:</span> <div>
<span>Episodes:</span>
<div *ngFor="let episode of seasons.episodes"> <div *ngFor="let episode of seasons.episodes">
<!--Episodes--> <!--Episodes-->
<span># {{episode.episodeNumber}} | {{episode.title}}</span> <span># {{episode.episodeNumber}} | {{episode.title}}</span>
<span *ngIf="episode.available" class="label label-success">Available</span> <span *ngIf="episode.available" class="label label-success">Available</span>
</div>
</div>
</div>
<div class="col-md-3">
<button *ngIf="!child.approved" type="button" (click)="approveSeasonRequest(child)" class="btn btn-sm btn-success-outline" style="text-align: right"><i class="fa fa-plus"></i> Approve</button>
<button *ngIf="!child.approved && !child.available && !child.denied" type="button" (click)="denySeasonRequest(child)" class="btn btn-sm btn-danger-outline" style="text-align: right"><i class="fa fa-plus"></i> Deny</button>
</div> </div>
</div> </div>
<hr />
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="col-md-3">
<button type="button" class="btn btn-danger-outline" (click)="showChildDialogue=false">Close</button> <button *ngIf="!child.approved" type="button" (click)="approveSeasonRequest(child)" class="btn btn-sm btn-success-outline" style="text-align: right"><i class="fa fa-plus"></i> Approve</button>
<button *ngIf="child.approved && !child.available" type="button" [disabled]="true" class="btn btn-sm btn-primary-outline" style="text-align: right"><i class="fa fa-plus"></i> Processing</button>
<button *ngIf="!child.approved && !child.available && !child.denied" type="button" (click)="denySeasonRequest(child)" class="btn btn-sm btn-danger-outline" style="text-align: right"><i class="fa fa-plus"></i> Deny</button>
</div> </div>
</div> </div>
<hr />
</div> </div>
</div> </p-dialog>
<!--<div class="modal fade in" *ngIf="showChildDialogue" style="display: block;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" (click)="showChildDialogue=false">&times;</button>
<h4 class="modal-title">{{selectedSeason?.title}}</h4>
</div>
<div class="modal-body">
<div class="row" *ngFor="let child of selectedSeason.childRequests">
<div class="col-md-12">
<div class="col-md-9">
<span class="col-md-12">Requested By: <b>{{child.requestedUser.username}}</b></span>
<span *ngIf="child.approved && !child.available" class="label label-info">Processing Request</span>
<span *ngIf="child.denied" class="label label-danger">Request Denied</span>
<span *ngIf="child.deniedReason" title="{{child.deniedReason}}"><i class="fa fa-info-circle"></i></span>
<span *ngIf="!child.approved && !child.availble && !child.denied" class="label label-warning">Pending Approval</span>
<div class="col-md-12" *ngFor="let seasons of child.seasonRequests">
<span>Season: {{seasons.seasonNumber}}</span>
<span>Episodes:</span>
<div *ngFor="let episode of seasons.episodes">
<span># {{episode.episodeNumber}} | {{episode.title}}</span>
<span *ngIf="episode.available" class="label label-success">Available</span>
</div>
</div>
</div>
<div class="col-md-3">
<button *ngIf="!child.approved" type="button" (click)="approveSeasonRequest(child)" class="btn btn-sm btn-success-outline" style="text-align: right"><i class="fa fa-plus"></i> Approve</button>
<button *ngIf="child.approved && !child.available" type="button" [disabled]="true" class="btn btn-sm btn-primary-outline" style="text-align: right"><i class="fa fa-plus"></i> Processing</button>
<button *ngIf="!child.approved && !child.available && !child.denied" type="button" (click)="denySeasonRequest(child)" class="btn btn-sm btn-danger-outline" style="text-align: right"><i class="fa fa-plus"></i> Deny</button>
</div>
</div>
<hr />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger-outline" (click)="showChildDialogue=false">Close</button>
</div>
</div>
</div>
</div>-->

View file

@ -31,7 +31,7 @@
<div id="{{id}}imgDiv" class="col-sm-2"> <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"> <img *ngIf="result.posterPath" class="img-responsive poster" src="https://image.tmdb.org/t/p/w150/{{result.posterPath}}" alt="poster">
</div> </div>
<div class="col-sm-8"> <div class="col-sm-8">

View file

@ -10,7 +10,7 @@ import { NotificationService } from '../services/notification.service';
import { ISearchTvResult } from '../interfaces/ISearchTvResult'; import { ISearchTvResult } from '../interfaces/ISearchTvResult';
import { IRequestEngineResult } from '../interfaces/IRequestEngineResult'; import { IRequestEngineResult } from '../interfaces/IRequestEngineResult';
import { IEpisodesRequested } from "../interfaces/IRequestModel"; import { IEpisodesRequests } from "../interfaces/IRequestModel";
@Component({ @Component({
templateUrl: './seriesinformation.component.html', templateUrl: './seriesinformation.component.html',
@ -33,7 +33,7 @@ export class SeriesInformationComponent implements OnInit, OnDestroy {
private seriesId: number; private seriesId: number;
public series: ISearchTvResult; public series: ISearchTvResult;
requestedEpisodes: IEpisodesRequested[] = []; requestedEpisodes: IEpisodesRequests[] = [];
ngOnInit(): void { ngOnInit(): void {
@ -61,7 +61,7 @@ export class SeriesInformationComponent implements OnInit, OnDestroy {
}); });
} }
public addRequest(episode: IEpisodesRequested) { public addRequest(episode: IEpisodesRequests) {
episode.requested = true; episode.requested = true;
} }

View file

@ -37,7 +37,7 @@
<div class="row"> <div class="row">
<div class="col-sm-2"> <div class="col-sm-2">
<img *ngIf="result.banner" class="img-responsive" width="150" [src]="result.banner" alt="poster"> <img *ngIf="result.banner" class="img-responsive poster" width="150" [src]="result.banner" alt="poster">
</div> </div>
<div class="col-sm-8"> <div class="col-sm-8">

View file

@ -1,9 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using Ombi.Core.Models.Requests; using Ombi.Store.Entities.Requests;
namespace Ombi.Models namespace Ombi.Models
{ {
public class RequestGridModel<T> where T : BaseRequestModel public class RequestGridModel<T> where T : BaseRequest
{ {
public IEnumerable<T> Available { get; set; } public IEnumerable<T> Available { get; set; }
public IEnumerable<T> New { get; set; } public IEnumerable<T> New { get; set; }

View file

@ -14,3 +14,14 @@ $bg-colour-disabled: #252424;
background: $primary-colour !important; background: $primary-colour !important;
color: white; color: white;
} }
#dialogOverride > div > .ui-dialog-content {
border: 1px solid $bg-colour-disabled !important;
background: $bg-colour !important;
color: white;
}
/*#dialogOverride > div > .ui-dialog-titlebar {
background: $primary-colour !important;
color: white;
}*/

View file

@ -734,4 +734,9 @@ body {
textarea { textarea {
resize: vertical; resize: vertical;
}
.poster {
box-shadow: 5px 5px 30px #000000;
border-radius: 30px;
} }