mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-08 06:00:50 -07:00
feat: Recently requested improvements (#4755)
* feat(discover): ✨ Admins can now approve the Recently Requested list * feat(discover): ⚡ Images for the recently requested area are now loading faster and just better all around * test: ✅ Added automation for the new feature
This commit is contained in:
parent
b0b1764f38
commit
ff04d87534
18 changed files with 292 additions and 95 deletions
|
@ -37,6 +37,9 @@ namespace Ombi.Core.Tests.Services
|
||||||
.ForEach(b => _fixture.Behaviors.Remove(b));
|
.ForEach(b => _fixture.Behaviors.Remove(b));
|
||||||
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
|
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
|
||||||
_mocker = new AutoMocker();
|
_mocker = new AutoMocker();
|
||||||
|
|
||||||
|
_mocker.Setup<ICurrentUser, Task<OmbiUser>>(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "test", Alias = "alias", Language = "en" });
|
||||||
|
_mocker.Setup<ICurrentUser, string>(x => x.Username).Returns("test");
|
||||||
_subject = _mocker.CreateInstance<RecentlyRequestedService>();
|
_subject = _mocker.CreateInstance<RecentlyRequestedService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,8 +73,6 @@ namespace Ombi.Core.Tests.Services
|
||||||
_mocker.Setup<IMovieRequestRepository, IQueryable<MovieRequests>>(x => x.GetAll()).Returns(movies.AsQueryable().BuildMock().Object);
|
_mocker.Setup<IMovieRequestRepository, IQueryable<MovieRequests>>(x => x.GetAll()).Returns(movies.AsQueryable().BuildMock().Object);
|
||||||
_mocker.Setup<IMusicRequestRepository, IQueryable<AlbumRequest>>(x => x.GetAll()).Returns(albums.AsQueryable().BuildMock().Object);
|
_mocker.Setup<IMusicRequestRepository, IQueryable<AlbumRequest>>(x => x.GetAll()).Returns(albums.AsQueryable().BuildMock().Object);
|
||||||
_mocker.Setup<ITvRequestRepository, IQueryable<ChildRequests>>(x => x.GetChild()).Returns(chilRequests.AsQueryable().BuildMock().Object);
|
_mocker.Setup<ITvRequestRepository, IQueryable<ChildRequests>>(x => x.GetChild()).Returns(chilRequests.AsQueryable().BuildMock().Object);
|
||||||
_mocker.Setup<ICurrentUser, Task<OmbiUser>>(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "test", Alias = "alias" });
|
|
||||||
_mocker.Setup<ICurrentUser, string>(x => x.Username).Returns("test");
|
|
||||||
|
|
||||||
var result = await _subject.GetRecentlyRequested(CancellationToken.None);
|
var result = await _subject.GetRecentlyRequested(CancellationToken.None);
|
||||||
|
|
||||||
|
@ -134,8 +135,6 @@ namespace Ombi.Core.Tests.Services
|
||||||
_mocker.Setup<IMovieRequestRepository, IQueryable<MovieRequests>>(x => x.GetAll()).Returns(movies.AsQueryable().BuildMock().Object);
|
_mocker.Setup<IMovieRequestRepository, IQueryable<MovieRequests>>(x => x.GetAll()).Returns(movies.AsQueryable().BuildMock().Object);
|
||||||
_mocker.Setup<IMusicRequestRepository, IQueryable<AlbumRequest>>(x => x.GetAll()).Returns(albums.AsQueryable().BuildMock().Object);
|
_mocker.Setup<IMusicRequestRepository, IQueryable<AlbumRequest>>(x => x.GetAll()).Returns(albums.AsQueryable().BuildMock().Object);
|
||||||
_mocker.Setup<ITvRequestRepository, IQueryable<ChildRequests>>(x => x.GetChild()).Returns(chilRequests.AsQueryable().BuildMock().Object);
|
_mocker.Setup<ITvRequestRepository, IQueryable<ChildRequests>>(x => x.GetChild()).Returns(chilRequests.AsQueryable().BuildMock().Object);
|
||||||
_mocker.Setup<ICurrentUser, Task<OmbiUser>>(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "test", Alias = "alias" });
|
|
||||||
_mocker.Setup<ICurrentUser, string>(x => x.Username).Returns("test");
|
|
||||||
|
|
||||||
var result = await _subject.GetRecentlyRequested(CancellationToken.None);
|
var result = await _subject.GetRecentlyRequested(CancellationToken.None);
|
||||||
|
|
||||||
|
@ -167,8 +166,6 @@ namespace Ombi.Core.Tests.Services
|
||||||
_mocker.Setup<IMovieRequestRepository, IQueryable<MovieRequests>>(x => x.GetAll()).Returns(movies.AsQueryable().BuildMock().Object);
|
_mocker.Setup<IMovieRequestRepository, IQueryable<MovieRequests>>(x => x.GetAll()).Returns(movies.AsQueryable().BuildMock().Object);
|
||||||
_mocker.Setup<IMusicRequestRepository, IQueryable<AlbumRequest>>(x => x.GetAll()).Returns(albums.AsQueryable().BuildMock().Object);
|
_mocker.Setup<IMusicRequestRepository, IQueryable<AlbumRequest>>(x => x.GetAll()).Returns(albums.AsQueryable().BuildMock().Object);
|
||||||
_mocker.Setup<ITvRequestRepository, IQueryable<ChildRequests>>(x => x.GetChild()).Returns(chilRequests.AsQueryable().BuildMock().Object);
|
_mocker.Setup<ITvRequestRepository, IQueryable<ChildRequests>>(x => x.GetChild()).Returns(chilRequests.AsQueryable().BuildMock().Object);
|
||||||
_mocker.Setup<ICurrentUser, Task<OmbiUser>>(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "test", Alias = "alias" });
|
|
||||||
_mocker.Setup<ICurrentUser, string>(x => x.Username).Returns("test");
|
|
||||||
|
|
||||||
var result = await _subject.GetRecentlyRequested(CancellationToken.None);
|
var result = await _subject.GetRecentlyRequested(CancellationToken.None);
|
||||||
|
|
||||||
|
|
|
@ -17,5 +17,8 @@ namespace Ombi.Core.Models.Requests
|
||||||
public DateTime ReleaseDate { get; set; }
|
public DateTime ReleaseDate { get; set; }
|
||||||
public bool Approved { get; set; }
|
public bool Approved { get; set; }
|
||||||
public string MediaId { get; set; }
|
public string MediaId { get; set; }
|
||||||
|
|
||||||
|
public string PosterPath { get; set; }
|
||||||
|
public string Background { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Ombi.Api.TheMovieDb;
|
||||||
using Ombi.Core.Authentication;
|
using Ombi.Core.Authentication;
|
||||||
using Ombi.Core.Engine.Interfaces;
|
using Ombi.Core.Engine.Interfaces;
|
||||||
using Ombi.Core.Helpers;
|
using Ombi.Core.Helpers;
|
||||||
|
@ -12,7 +13,6 @@ using Ombi.Store.Repository.Requests;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using static Ombi.Core.Engine.BaseMediaEngine;
|
using static Ombi.Core.Engine.BaseMediaEngine;
|
||||||
|
@ -26,7 +26,8 @@ namespace Ombi.Core.Services
|
||||||
private readonly IMusicRequestRepository _musicRequestRepository;
|
private readonly IMusicRequestRepository _musicRequestRepository;
|
||||||
private readonly ISettingsService<CustomizationSettings> _customizationSettings;
|
private readonly ISettingsService<CustomizationSettings> _customizationSettings;
|
||||||
private readonly ISettingsService<OmbiSettings> _ombiSettings;
|
private readonly ISettingsService<OmbiSettings> _ombiSettings;
|
||||||
|
private readonly IMovieDbApi _movieDbApi;
|
||||||
|
private readonly ICacheService _cache;
|
||||||
private const int AmountToTake = 7;
|
private const int AmountToTake = 7;
|
||||||
|
|
||||||
public RecentlyRequestedService(
|
public RecentlyRequestedService(
|
||||||
|
@ -37,13 +38,17 @@ namespace Ombi.Core.Services
|
||||||
ISettingsService<OmbiSettings> ombiSettings,
|
ISettingsService<OmbiSettings> ombiSettings,
|
||||||
ICurrentUser user,
|
ICurrentUser user,
|
||||||
OmbiUserManager um,
|
OmbiUserManager um,
|
||||||
IRuleEvaluator rules) : base(user, um, rules)
|
IRuleEvaluator rules,
|
||||||
|
IMovieDbApi movieDbApi,
|
||||||
|
ICacheService cache) : base(user, um, rules)
|
||||||
{
|
{
|
||||||
_movieRequestRepository = movieRequestRepository;
|
_movieRequestRepository = movieRequestRepository;
|
||||||
_tvRequestRepository = tvRequestRepository;
|
_tvRequestRepository = tvRequestRepository;
|
||||||
_musicRequestRepository = musicRequestRepository;
|
_musicRequestRepository = musicRequestRepository;
|
||||||
_customizationSettings = customizationSettings;
|
_customizationSettings = customizationSettings;
|
||||||
_ombiSettings = ombiSettings;
|
_ombiSettings = ombiSettings;
|
||||||
|
_movieDbApi = movieDbApi;
|
||||||
|
_cache = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<RecentlyRequestedModel>> GetRecentlyRequested(CancellationToken cancellationToken)
|
public async Task<IEnumerable<RecentlyRequestedModel>> GetRecentlyRequested(CancellationToken cancellationToken)
|
||||||
|
@ -65,8 +70,10 @@ namespace Ombi.Core.Services
|
||||||
|
|
||||||
var model = new List<RecentlyRequestedModel>();
|
var model = new List<RecentlyRequestedModel>();
|
||||||
|
|
||||||
|
var lang = await DefaultLanguageCode();
|
||||||
foreach (var item in await recentMovieRequests.ToListAsync(cancellationToken))
|
foreach (var item in await recentMovieRequests.ToListAsync(cancellationToken))
|
||||||
{
|
{
|
||||||
|
var images = await _cache.GetOrAddAsync($"{CacheKeys.TmdbImages}movie{item.TheMovieDbId}", () => _movieDbApi.GetMovieImages(item.TheMovieDbId.ToString(), cancellationToken), DateTimeOffset.Now.AddDays(1));
|
||||||
model.Add(new RecentlyRequestedModel
|
model.Add(new RecentlyRequestedModel
|
||||||
{
|
{
|
||||||
RequestId = item.Id,
|
RequestId = item.Id,
|
||||||
|
@ -80,6 +87,8 @@ namespace Ombi.Core.Services
|
||||||
UserId = hideUsers.Hide ? string.Empty : item.RequestedUserId,
|
UserId = hideUsers.Hide ? string.Empty : item.RequestedUserId,
|
||||||
Username = hideUsers.Hide ? string.Empty : item.RequestedUser.UserAlias,
|
Username = hideUsers.Hide ? string.Empty : item.RequestedUser.UserAlias,
|
||||||
MediaId = item.TheMovieDbId.ToString(),
|
MediaId = item.TheMovieDbId.ToString(),
|
||||||
|
PosterPath = images?.posters?.Where(x => lang.Equals(x?.iso_639_1, StringComparison.InvariantCultureIgnoreCase))?.OrderByDescending(x => x.vote_count)?.Select(x => x.file_path)?.FirstOrDefault(),
|
||||||
|
Background = images?.backdrops?.Where(x => lang.Equals(x?.iso_639_1, StringComparison.InvariantCultureIgnoreCase))?.OrderByDescending(x => x.vote_count)?.Select(x => x.file_path)?.FirstOrDefault(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,6 +112,9 @@ namespace Ombi.Core.Services
|
||||||
|
|
||||||
foreach (var item in await recentTvRequests.ToListAsync(cancellationToken))
|
foreach (var item in await recentTvRequests.ToListAsync(cancellationToken))
|
||||||
{
|
{
|
||||||
|
var providerId = item.ParentRequest.ExternalProviderId.ToString();
|
||||||
|
var images = await _cache.GetOrAddAsync($"{CacheKeys.TmdbImages}tv{providerId}", () => _movieDbApi.GetTvImages(providerId.ToString(), cancellationToken), DateTimeOffset.Now.AddDays(1));
|
||||||
|
|
||||||
var partialAvailability = item.SeasonRequests.SelectMany(x => x.Episodes).Any(e => e.Available);
|
var partialAvailability = item.SeasonRequests.SelectMany(x => x.Episodes).Any(e => e.Available);
|
||||||
model.Add(new RecentlyRequestedModel
|
model.Add(new RecentlyRequestedModel
|
||||||
{
|
{
|
||||||
|
@ -117,7 +129,9 @@ namespace Ombi.Core.Services
|
||||||
Type = RequestType.TvShow,
|
Type = RequestType.TvShow,
|
||||||
UserId = hideUsers.Hide ? string.Empty : item.RequestedUserId,
|
UserId = hideUsers.Hide ? string.Empty : item.RequestedUserId,
|
||||||
Username = hideUsers.Hide ? string.Empty : item.RequestedUser.UserAlias,
|
Username = hideUsers.Hide ? string.Empty : item.RequestedUser.UserAlias,
|
||||||
MediaId = item.ParentRequest.ExternalProviderId.ToString()
|
MediaId = providerId.ToString(),
|
||||||
|
PosterPath = images?.posters?.Where(x => lang.Equals(x?.iso_639_1, StringComparison.InvariantCultureIgnoreCase))?.OrderByDescending(x => x.vote_count)?.Select(x => x.file_path)?.FirstOrDefault(),
|
||||||
|
Background = images?.backdrops?.Where(x => lang.Equals(x?.iso_639_1, StringComparison.InvariantCultureIgnoreCase))?.OrderByDescending(x => x.vote_count)?.Select(x => x.file_path)?.FirstOrDefault(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +148,7 @@ namespace Ombi.Core.Services
|
||||||
UserId = user.Id
|
UserId = user.Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
var settings = await _ombiSettings.GetSettingsAsync();
|
var settings = await GetOmbiSettings();
|
||||||
var result = new HideResult
|
var result = new HideResult
|
||||||
{
|
{
|
||||||
Hide = settings.HideRequestsUsers,
|
Hide = settings.HideRequestsUsers,
|
||||||
|
@ -142,5 +156,28 @@ namespace Ombi.Core.Services
|
||||||
};
|
};
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
protected async Task<string> DefaultLanguageCode()
|
||||||
|
{
|
||||||
|
var user = await GetUser();
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return "en";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(user.Language))
|
||||||
|
{
|
||||||
|
var s = await GetOmbiSettings();
|
||||||
|
return s.DefaultLanguageCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return user.Language;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private OmbiSettings ombiSettings;
|
||||||
|
protected async Task<OmbiSettings> GetOmbiSettings()
|
||||||
|
{
|
||||||
|
return ombiSettings ??= await _ombiSettings.GetSettingsAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ namespace Ombi.Api.TheMovieDb
|
||||||
Task<List<Language>> GetLanguages(CancellationToken cancellationToken);
|
Task<List<Language>> GetLanguages(CancellationToken cancellationToken);
|
||||||
Task<List<WatchProvidersResults>> SearchWatchProviders(string media, string searchTerm, CancellationToken cancellationToken);
|
Task<List<WatchProvidersResults>> SearchWatchProviders(string media, string searchTerm, CancellationToken cancellationToken);
|
||||||
Task<List<MovieDbSearchResult>> AdvancedSearch(DiscoverModel model, int page, CancellationToken cancellationToken);
|
Task<List<MovieDbSearchResult>> AdvancedSearch(DiscoverModel model, int page, CancellationToken cancellationToken);
|
||||||
Task<TvImages> GetTvImages(string theMovieDbId, CancellationToken token);
|
Task<MovieDbImages> GetTvImages(string theMovieDbId, CancellationToken token);
|
||||||
|
Task<MovieDbImages> GetMovieImages(string theMovieDbId, CancellationToken token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Ombi.Api.TheMovieDb.Models
|
namespace Ombi.Api.TheMovieDb.Models
|
||||||
{
|
{
|
||||||
public class TvImages
|
public class MovieDbImages
|
||||||
{
|
{
|
||||||
public Backdrop[] backdrops { get; set; }
|
public Backdrop[] backdrops { get; set; }
|
||||||
public int id { get; set; }
|
public int id { get; set; }
|
||||||
|
|
|
@ -514,12 +514,20 @@ namespace Ombi.Api.TheMovieDb
|
||||||
return Api.Request<WatchProviders>(request, token);
|
return Api.Request<WatchProviders>(request, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TvImages> GetTvImages(string theMovieDbId, CancellationToken token)
|
public Task<MovieDbImages> GetTvImages(string theMovieDbId, CancellationToken token)
|
||||||
{
|
{
|
||||||
var request = new Request($"tv/{theMovieDbId}/images", BaseUri, HttpMethod.Get);
|
var request = new Request($"tv/{theMovieDbId}/images", BaseUri, HttpMethod.Get);
|
||||||
request.AddQueryString("api_key", ApiToken);
|
request.AddQueryString("api_key", ApiToken);
|
||||||
|
|
||||||
return Api.Request<TvImages>(request, token);
|
return Api.Request<MovieDbImages>(request, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<MovieDbImages> GetMovieImages(string theMovieDbId, CancellationToken token)
|
||||||
|
{
|
||||||
|
var request = new Request($"movie/{theMovieDbId}/images", BaseUri, HttpMethod.Get);
|
||||||
|
request.AddQueryString("api_key", ApiToken);
|
||||||
|
|
||||||
|
return Api.Request<MovieDbImages>(request, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddDiscoverSettings(Request request)
|
private async Task AddDiscoverSettings(Request request)
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
.detailed-container {
|
|
||||||
width: 400px;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
::ng-deep .poster {
|
|
||||||
border-radius: 10px;
|
|
||||||
opacity: 1;
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
transition: .5s ease;
|
|
||||||
backface-visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { MatButtonModule } from "@angular/material/button";
|
||||||
selector: 'ombi-button',
|
selector: 'ombi-button',
|
||||||
imports: [...OmbiCommonModules, MatButtonModule],
|
imports: [...OmbiCommonModules, MatButtonModule],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
styleUrls: ['./button.component.scss'],
|
|
||||||
template: `
|
template: `
|
||||||
<button [id]="id" [type]="type" [class]="class" [data-toggle]="dataToggle" mat-raised-button [data-target]="dataTarget">{{text}}</button>
|
<button [id]="id" [type]="type" [class]="class" [data-toggle]="dataToggle" mat-raised-button [data-target]="dataTarget">{{text}}</button>
|
||||||
`
|
`
|
||||||
|
@ -17,7 +16,7 @@ import { MatButtonModule } from "@angular/material/button";
|
||||||
@Input() public text: string;
|
@Input() public text: string;
|
||||||
|
|
||||||
@Input() public id: string;
|
@Input() public id: string;
|
||||||
@Input() public type: string;
|
@Input() public type: string = "primary";
|
||||||
@Input() public class: string;
|
@Input() public class: string;
|
||||||
@Input('data-toggle') public dataToggle: string;
|
@Input('data-toggle') public dataToggle: string;
|
||||||
@Input('data-target') public dataTarget: string;
|
@Input('data-target') public dataTarget: string;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div id="detailed-{{request.mediaId}}" class="detailed-container" (click)="click()" [style.background-image]="background">
|
<div id="detailed-{{request.mediaId}}" class="detailed-container" [style.background-image]="background">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xl-5 col-lg-5 col-md-5 col-sm-12 posterColumn">
|
<div class="col-xl-5 col-lg-5 col-md-5 col-sm-12 posterColumn">
|
||||||
<ombi-image [src]="request.posterPath" [type]="request.type" class="poster" alt="{{request.title}}">
|
<ombi-image (click)="click()" [src]="request.posterPath" [type]="request.type" class="poster" alt="{{request.title}}">
|
||||||
</ombi-image>
|
</ombi-image>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-7 col-lg-7 col-md-7 col-sm-12">
|
<div class="col-xl-7 col-lg-7 col-md-7 col-sm-12">
|
||||||
|
@ -20,6 +20,11 @@
|
||||||
<p id="detailed-request-status-{{request.mediaId}}">{{'MediaDetails.Status' | translate}} <span class="badge badge-{{getClass(request)}}">{{getStatus(request) | translate}}</span></p>
|
<p id="detailed-request-status-{{request.mediaId}}">{{'MediaDetails.Status' | translate}} <span class="badge badge-{{getClass(request)}}">{{getStatus(request) | translate}}</span></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row action-items">
|
||||||
|
<div class="col-12" *ngIf="isAdmin">
|
||||||
|
<button *ngIf="!request.approved" id="detailed-request-approve-{{request.mediaId}}" color="accent" mat-raised-button (click)="approve()">{{'Common.Approve' | translate}}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
.detailed-container {
|
.detailed-container {
|
||||||
width: 400px;
|
width: 400px;
|
||||||
height: auto;
|
height: 250px;
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
@media (max-width:768px) {
|
@media (max-width:768px) {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
background-color: $ombi-background-accent;
|
background-color: $ombi-background-accent;
|
||||||
|
@ -36,12 +37,18 @@
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
display: block;
|
display: block;
|
||||||
|
height: 225px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 200px;
|
|
||||||
transition: .5s ease;
|
transition: .5s ease;
|
||||||
backface-visibility: hidden;
|
backface-visibility: hidden;
|
||||||
border: 1px solid #35465c;
|
border: 1px solid #35465c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.action-items {
|
||||||
|
@media (min-width:768px) {
|
||||||
|
bottom: 0;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ NewMovieRequest.args = {
|
||||||
overview: 'The Matrix is a movie about a group of people who are forced to fight against a powerful computer system that controls them.',
|
overview: 'The Matrix is a movie about a group of people who are forced to fight against a powerful computer system that controls them.',
|
||||||
releaseDate: new Date(2020, 1, 1),
|
releaseDate: new Date(2020, 1, 1),
|
||||||
} as IRecentlyRequested,
|
} as IRecentlyRequested,
|
||||||
|
isAdmin: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MovieNoUsername = Template.bind({});
|
export const MovieNoUsername = Template.bind({});
|
||||||
|
@ -206,4 +207,60 @@ TvNoUsername.args = {
|
||||||
mediaId: '603',
|
mediaId: '603',
|
||||||
releaseDate: new Date(2020, 1, 1),
|
releaseDate: new Date(2020, 1, 1),
|
||||||
} as IRecentlyRequested,
|
} as IRecentlyRequested,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AdminNewMovie = Template.bind({});
|
||||||
|
// More on args: https://storybook.js.org/docs/angular/writing-stories/args
|
||||||
|
AdminNewMovie.args = {
|
||||||
|
request: {
|
||||||
|
title: 'The Matrix',
|
||||||
|
approved: false,
|
||||||
|
available: false,
|
||||||
|
tvPartiallyAvailable: false,
|
||||||
|
requestDate: new Date(2022, 1, 1),
|
||||||
|
username: 'John Doe',
|
||||||
|
userId: '12345',
|
||||||
|
type: RequestType.movie,
|
||||||
|
mediaId: '603',
|
||||||
|
overview: 'The Matrix is a movie about a group of people who are forced to fight against a powerful computer system that controls them.',
|
||||||
|
releaseDate: new Date(2020, 1, 1),
|
||||||
|
} as IRecentlyRequested,
|
||||||
|
isAdmin: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AdminTvShow = Template.bind({});
|
||||||
|
// More on args: https://storybook.js.org/docs/angular/writing-stories/args
|
||||||
|
AdminTvShow.args = {
|
||||||
|
request: {
|
||||||
|
title: 'For All Mankind',
|
||||||
|
approved: false,
|
||||||
|
available: false,
|
||||||
|
tvPartiallyAvailable: true,
|
||||||
|
requestDate: new Date(2022, 1, 1),
|
||||||
|
userId: '12345',
|
||||||
|
type: RequestType.tvShow,
|
||||||
|
mediaId: '603',
|
||||||
|
username: 'John Doe',
|
||||||
|
releaseDate: new Date(2020, 1, 1),
|
||||||
|
} as IRecentlyRequested,
|
||||||
|
isAdmin: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AdminApprovedMovie = Template.bind({});
|
||||||
|
// More on args: https://storybook.js.org/docs/angular/writing-stories/args
|
||||||
|
AdminApprovedMovie.args = {
|
||||||
|
request: {
|
||||||
|
title: 'The Matrix',
|
||||||
|
approved: true,
|
||||||
|
available: false,
|
||||||
|
tvPartiallyAvailable: false,
|
||||||
|
requestDate: new Date(2022, 1, 1),
|
||||||
|
username: 'John Doe',
|
||||||
|
userId: '12345',
|
||||||
|
type: RequestType.movie,
|
||||||
|
mediaId: '603',
|
||||||
|
overview: 'The Matrix is a movie about a group of people who are forced to fight against a powerful computer system that controls them.',
|
||||||
|
releaseDate: new Date(2020, 1, 1),
|
||||||
|
} as IRecentlyRequested,
|
||||||
|
isAdmin: true,
|
||||||
};
|
};
|
|
@ -1,4 +1,4 @@
|
||||||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
|
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
|
||||||
import { IRecentlyRequested, RequestType } from "../../interfaces";
|
import { IRecentlyRequested, RequestType } from "../../interfaces";
|
||||||
import { ImageService } from "app/services";
|
import { ImageService } from "app/services";
|
||||||
import { Subject, takeUntil } from "rxjs";
|
import { Subject, takeUntil } from "rxjs";
|
||||||
|
@ -7,14 +7,14 @@ import { DomSanitizer, SafeStyle } from "@angular/platform-browser";
|
||||||
@Component({
|
@Component({
|
||||||
standalone: false,
|
standalone: false,
|
||||||
selector: 'ombi-detailed-card',
|
selector: 'ombi-detailed-card',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
||||||
templateUrl: './detailed-card.component.html',
|
templateUrl: './detailed-card.component.html',
|
||||||
styleUrls: ['./detailed-card.component.scss']
|
styleUrls: ['./detailed-card.component.scss']
|
||||||
})
|
})
|
||||||
export class DetailedCardComponent implements OnInit, OnDestroy {
|
export class DetailedCardComponent implements OnInit, OnDestroy {
|
||||||
@Input() public request: IRecentlyRequested;
|
@Input() public request: IRecentlyRequested;
|
||||||
|
@Input() public isAdmin: boolean = false;
|
||||||
@Output() public onClick: EventEmitter<void> = new EventEmitter<void>();
|
@Output() public onClick: EventEmitter<void> = new EventEmitter<void>();
|
||||||
|
@Output() public onApprove: EventEmitter<void> = new EventEmitter<void>();
|
||||||
|
|
||||||
public RequestType = RequestType;
|
public RequestType = RequestType;
|
||||||
public loading: false;
|
public loading: false;
|
||||||
|
@ -27,20 +27,10 @@ import { DomSanitizer, SafeStyle } from "@angular/platform-browser";
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
if (!this.request.posterPath) {
|
if (!this.request.posterPath) {
|
||||||
switch (this.request.type) {
|
this.loadImages();
|
||||||
case RequestType.movie:
|
} else {
|
||||||
this.imageService.getMoviePoster(this.request.mediaId).pipe(takeUntil(this.$imageSub)).subscribe(x => this.request.posterPath = x);
|
this.request.posterPath = `https://image.tmdb.org/t/p/w300${this.request.posterPath}`;
|
||||||
this.imageService.getMovieBackground(this.request.mediaId).pipe(takeUntil(this.$imageSub)).subscribe(x => {
|
this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5)), url(https://image.tmdb.org/t/p/w300" + this.request.background + ")");
|
||||||
this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5)), url(" + x + ")");
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case RequestType.tvShow:
|
|
||||||
this.imageService.getTmdbTvPoster(Number(this.request.mediaId)).pipe(takeUntil(this.$imageSub)).subscribe(x => this.request.posterPath = `https://image.tmdb.org/t/p/w300${x}`);
|
|
||||||
this.imageService.getTmdbTvBackground(Number(this.request.mediaId)).pipe(takeUntil(this.$imageSub)).subscribe(x => {
|
|
||||||
this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5)), url(https://image.tmdb.org/t/p/w300" + x + ")");
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +52,10 @@ import { DomSanitizer, SafeStyle } from "@angular/platform-browser";
|
||||||
this.onClick.emit();
|
this.onClick.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public approve() {
|
||||||
|
this.onApprove.emit();
|
||||||
|
}
|
||||||
|
|
||||||
public getClass(request: IRecentlyRequested) {
|
public getClass(request: IRecentlyRequested) {
|
||||||
if (request.available || request.tvPartiallyAvailable) {
|
if (request.available || request.tvPartiallyAvailable) {
|
||||||
return "success";
|
return "success";
|
||||||
|
@ -78,4 +72,21 @@ import { DomSanitizer, SafeStyle } from "@angular/platform-browser";
|
||||||
this.$imageSub.complete();
|
this.$imageSub.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private loadImages() {
|
||||||
|
switch (this.request.type) {
|
||||||
|
case RequestType.movie:
|
||||||
|
this.imageService.getMoviePoster(this.request.mediaId).pipe(takeUntil(this.$imageSub)).subscribe(x => this.request.posterPath = x);
|
||||||
|
this.imageService.getMovieBackground(this.request.mediaId).pipe(takeUntil(this.$imageSub)).subscribe(x => {
|
||||||
|
this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5)), url(" + x + ")");
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case RequestType.tvShow:
|
||||||
|
this.imageService.getTmdbTvPoster(Number(this.request.mediaId)).pipe(takeUntil(this.$imageSub)).subscribe(x => this.request.posterPath = `https://image.tmdb.org/t/p/w300${x}`);
|
||||||
|
this.imageService.getTmdbTvBackground(Number(this.request.mediaId)).pipe(takeUntil(this.$imageSub)).subscribe(x => {
|
||||||
|
this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5)), url(https://image.tmdb.org/t/p/w300" + x + ")");
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<p-carousel #carousel [value]="requests" [numVisible]="3" [numScroll]="1" [responsiveOptions]="responsiveOptions" [page]="0">
|
<p-carousel #carousel [value]="requests$ | async" [numVisible]="3" [numScroll]="1" [responsiveOptions]="responsiveOptions" [page]="0">
|
||||||
<ng-template let-result pTemplate="item">
|
<ng-template let-result pTemplate="item">
|
||||||
<ombi-detailed-card [request]="result" (onClick)="navigate(result)"></ombi-detailed-card>
|
<ombi-detailed-card [request]="result" [isAdmin]="isAdmin" (onClick)="navigate(result)" (onApprove)="approve(result)"></ombi-detailed-card>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</p-carousel>
|
</p-carousel>
|
|
@ -1,15 +1,13 @@
|
||||||
import { Component, OnInit, Input, ViewChild, Output, EventEmitter, OnDestroy } from "@angular/core";
|
import { Component, OnInit, Input, ViewChild, OnDestroy } from "@angular/core";
|
||||||
import { DiscoverOption, IDiscoverCardResult } from "../../interfaces";
|
import { IRecentlyRequested, IRequestEngineResult, RequestType } from "../../../interfaces";
|
||||||
import { IRecentlyRequested, ISearchMovieResult, ISearchTvResult, RequestType } from "../../../interfaces";
|
|
||||||
import { SearchV2Service } from "../../../services";
|
|
||||||
import { StorageService } from "../../../shared/storage/storage-service";
|
|
||||||
import { MatButtonToggleChange } from '@angular/material/button-toggle';
|
|
||||||
import { Carousel } from 'primeng/carousel';
|
import { Carousel } from 'primeng/carousel';
|
||||||
import { FeaturesFacade } from "../../../state/features/features.facade";
|
|
||||||
import { ResponsiveOptions } from "../carousel.options";
|
import { ResponsiveOptions } from "../carousel.options";
|
||||||
import { RequestServiceV2 } from "app/services/requestV2.service";
|
import { RequestServiceV2 } from "app/services/requestV2.service";
|
||||||
import { Subject, takeUntil } from "rxjs";
|
import { finalize, map, Observable, Subject, takeUntil, tap } from "rxjs";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
|
import { AuthService } from "app/auth/auth.service";
|
||||||
|
import { NotificationService, RequestService } from "app/services";
|
||||||
|
import { TranslateService } from "@ngx-translate/core";
|
||||||
|
|
||||||
export enum DiscoverType {
|
export enum DiscoverType {
|
||||||
Upcoming,
|
Upcoming,
|
||||||
|
@ -30,21 +28,22 @@ export class RecentlyRequestedListComponent implements OnInit, OnDestroy {
|
||||||
@Input() public isAdmin: boolean;
|
@Input() public isAdmin: boolean;
|
||||||
@ViewChild('carousel', {static: false}) carousel: Carousel;
|
@ViewChild('carousel', {static: false}) carousel: Carousel;
|
||||||
|
|
||||||
|
public requests$: Observable<IRecentlyRequested[]>;
|
||||||
public requests: IRecentlyRequested[];
|
|
||||||
|
|
||||||
public responsiveOptions: any;
|
public responsiveOptions: any;
|
||||||
public RequestType = RequestType;
|
public RequestType = RequestType;
|
||||||
public loadingFlag: boolean;
|
public loadingFlag: boolean;
|
||||||
public DiscoverType = DiscoverType;
|
public DiscoverType = DiscoverType;
|
||||||
public is4kEnabled = false;
|
|
||||||
|
|
||||||
private $loadSub = new Subject<void>();
|
private $loadSub = new Subject<void>();
|
||||||
|
|
||||||
constructor(private requestService: RequestServiceV2,
|
constructor(private requestServiceV2: RequestServiceV2,
|
||||||
private featureFacade: FeaturesFacade,
|
private requestService: RequestService,
|
||||||
private router: Router) {
|
private router: Router,
|
||||||
Carousel.prototype.onTouchMove = () => {},
|
private authService: AuthService,
|
||||||
|
private notificationService: NotificationService,
|
||||||
|
private translateService: TranslateService) {
|
||||||
|
Carousel.prototype.onTouchMove = () => {};
|
||||||
this.responsiveOptions = ResponsiveOptions;
|
this.responsiveOptions = ResponsiveOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,14 +53,43 @@ export class RecentlyRequestedListComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
this.loading();
|
|
||||||
this.loadData();
|
this.loadData();
|
||||||
|
this.isAdmin = this.authService.isAdmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
public navigate(request: IRecentlyRequested) {
|
public navigate(request: IRecentlyRequested) {
|
||||||
this.router.navigate([this.generateDetailsLink(request), request.mediaId]);
|
this.router.navigate([this.generateDetailsLink(request), request.mediaId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public approve(request: IRecentlyRequested) {
|
||||||
|
switch(request.type) {
|
||||||
|
case RequestType.movie:
|
||||||
|
this.requestService.approveMovie({id: request.requestId, is4K: false}).pipe(
|
||||||
|
map((res) => this.handleApproval(res, request))
|
||||||
|
).subscribe();
|
||||||
|
break;
|
||||||
|
case RequestType.tvShow:
|
||||||
|
this.requestService.approveChild({id: request.requestId}).pipe(
|
||||||
|
tap((res) => this.handleApproval(res, request))
|
||||||
|
).subscribe();
|
||||||
|
break;
|
||||||
|
case RequestType.album:
|
||||||
|
this.requestService.approveAlbum({id: request.requestId}).pipe(
|
||||||
|
tap((res) => this.handleApproval(res, request))
|
||||||
|
).subscribe();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleApproval(result: IRequestEngineResult, request: IRecentlyRequested) {
|
||||||
|
if (result.result) {
|
||||||
|
this.notificationService.success(this.translateService.instant("Requests.SuccessfullyApproved"));
|
||||||
|
request.approved = true;
|
||||||
|
} else {
|
||||||
|
this.notificationService.error(result.errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private generateDetailsLink(request: IRecentlyRequested): string {
|
private generateDetailsLink(request: IRecentlyRequested): string {
|
||||||
switch (request.type) {
|
switch (request.type) {
|
||||||
case RequestType.movie:
|
case RequestType.movie:
|
||||||
|
@ -74,13 +102,13 @@ export class RecentlyRequestedListComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadData() {
|
private loadData() {
|
||||||
this.requestService.getRecentlyRequested().pipe(takeUntil(this.$loadSub)).subscribe(x => {
|
this.requests$ = this.requestServiceV2.getRecentlyRequested().pipe(
|
||||||
this.requests = x;
|
tap(() => this.loading()),
|
||||||
this.finishLoading();
|
takeUntil(this.$loadSub),
|
||||||
});
|
finalize(() => this.finishLoading())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private loading() {
|
private loading() {
|
||||||
this.loadingFlag = true;
|
this.loadingFlag = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,4 +15,5 @@ export interface IRecentlyRequested {
|
||||||
type: RequestType;
|
type: RequestType;
|
||||||
|
|
||||||
posterPath: string;
|
posterPath: string;
|
||||||
|
background: string;
|
||||||
}
|
}
|
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
"OmbiDatabase": {
|
|
||||||
"Type": "MySQL",
|
|
||||||
"ConnectionString": "Server=192.168.68.118;Port=3306;Database=Ombi;User=ombi;"
|
|
||||||
},
|
|
||||||
"SettingsDatabase": {
|
|
||||||
"Type": "MySQL",
|
|
||||||
"ConnectionString": "Server=192.168.68.118;Port=3306;Database=Ombi;User=ombi;"
|
|
||||||
},
|
|
||||||
"ExternalDatabase": {
|
|
||||||
"Type": "MySQL",
|
|
||||||
"ConnectionString": "Server=192.168.68.118;Port=3306;Database=Ombi;User=ombi;"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -43,9 +43,13 @@ class DetailedCard {
|
||||||
return cy.get(`#detailed-request-status-${this.id}`);
|
return cy.get(`#detailed-request-status-${this.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get approveButton(): Cypress.Chainable<any> {
|
||||||
|
return cy.get(`#detailed-request-approve-${this.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
verifyTitle(expected: string): Cypress.Chainable<any> {
|
verifyTitle(expected: string): Cypress.Chainable<any> {
|
||||||
return this.title.should('have.text',expected);
|
return this.title.should('have.text',expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(id: string) {
|
constructor(id: string) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|
|
@ -44,6 +44,7 @@ describe("Discover Recently Requested Tests", () => {
|
||||||
const card = Page.recentlyRequested.getRequest("626735");
|
const card = Page.recentlyRequested.getRequest("626735");
|
||||||
card.verifyTitle("Dog");
|
card.verifyTitle("Dog");
|
||||||
card.status.should('contain.text', 'Pending');
|
card.status.should('contain.text', 'Pending');
|
||||||
|
card.approveButton.should('be.visible');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -69,6 +70,7 @@ describe("Discover Recently Requested Tests", () => {
|
||||||
const card = Page.recentlyRequested.getRequest("675353");
|
const card = Page.recentlyRequested.getRequest("675353");
|
||||||
card.verifyTitle("Sonic the Hedgehog 2");
|
card.verifyTitle("Sonic the Hedgehog 2");
|
||||||
card.status.should('contain.text', 'Available'); // Because admin auto request
|
card.status.should('contain.text', 'Available'); // Because admin auto request
|
||||||
|
card.approveButton.should('not.exist');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -94,6 +96,7 @@ describe("Discover Recently Requested Tests", () => {
|
||||||
const card = Page.recentlyRequested.getRequest("135647");
|
const card = Page.recentlyRequested.getRequest("135647");
|
||||||
card.verifyTitle("2 Good 2 Be True");
|
card.verifyTitle("2 Good 2 Be True");
|
||||||
card.status.should('contain.text', 'Available');
|
card.status.should('contain.text', 'Available');
|
||||||
|
card.approveButton.should('not.exist');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -119,6 +122,7 @@ describe("Discover Recently Requested Tests", () => {
|
||||||
const card = Page.recentlyRequested.getRequest("158415");
|
const card = Page.recentlyRequested.getRequest("158415");
|
||||||
card.verifyTitle("Pantanal");
|
card.verifyTitle("Pantanal");
|
||||||
card.status.should('contain.text', 'Partially Available');
|
card.status.should('contain.text', 'Partially Available');
|
||||||
|
card.approveButton.should('not.exist');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -143,6 +147,7 @@ describe("Discover Recently Requested Tests", () => {
|
||||||
const card = Page.recentlyRequested.getRequest("60574");
|
const card = Page.recentlyRequested.getRequest("60574");
|
||||||
card.verifyTitle("Peaky Blinders");
|
card.verifyTitle("Peaky Blinders");
|
||||||
card.status.should('contain.text', 'Pending');
|
card.status.should('contain.text', 'Pending');
|
||||||
|
card.approveButton.should('be.visible');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -161,4 +166,70 @@ describe("Discover Recently Requested Tests", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Approve Requested Movie", () => {
|
||||||
|
|
||||||
|
cy.requestMovie(55341);
|
||||||
|
|
||||||
|
cy.intercept("GET", "**/v2/Requests/recentlyRequested", (req) => {
|
||||||
|
req.reply((res) => {
|
||||||
|
const body = res.body;
|
||||||
|
const movie = body[0];
|
||||||
|
movie.available = false;
|
||||||
|
movie.approved = false;
|
||||||
|
|
||||||
|
body[0] = movie;
|
||||||
|
res.send(body);
|
||||||
|
});
|
||||||
|
}).as("response");
|
||||||
|
|
||||||
|
cy.intercept("POST", "**/v1/Request/Movie/Approve").as("approveCall");
|
||||||
|
|
||||||
|
Page.visit();
|
||||||
|
|
||||||
|
cy.wait("@response").then((_) => {
|
||||||
|
|
||||||
|
const card = Page.recentlyRequested.getRequest("55341");
|
||||||
|
card.approveButton.should('be.visible');
|
||||||
|
card.approveButton.click();
|
||||||
|
|
||||||
|
cy.wait("@approveCall").then((_) => {
|
||||||
|
card.status.should('contain.text', 'Approved');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it.only("Approve Requested Tv Show", () => {
|
||||||
|
|
||||||
|
cy.requestAllTv(71712);
|
||||||
|
|
||||||
|
cy.intercept("GET", "**/v2/Requests/recentlyRequested", (req) => {
|
||||||
|
req.reply((res) => {
|
||||||
|
const body = res.body;
|
||||||
|
const movie = body[0];
|
||||||
|
movie.available = false;
|
||||||
|
movie.approved = false;
|
||||||
|
|
||||||
|
body[0] = movie;
|
||||||
|
res.send(body);
|
||||||
|
});
|
||||||
|
}).as("response");
|
||||||
|
|
||||||
|
cy.intercept("POST", "**/v1/Request/tv/approve").as("approveCall");
|
||||||
|
|
||||||
|
Page.visit();
|
||||||
|
|
||||||
|
cy.wait("@response").then((_) => {
|
||||||
|
|
||||||
|
const card = Page.recentlyRequested.getRequest("71712");
|
||||||
|
card.approveButton.should('be.visible');
|
||||||
|
card.approveButton.click();
|
||||||
|
|
||||||
|
cy.wait("@approveCall").then((_) => {
|
||||||
|
card.status.should('contain.text', 'Approved');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue