From 8b9c37562846a2e78a492bd17349f617892798ec Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Wed, 4 Apr 2018 13:48:40 +0100 Subject: [PATCH 01/46] Made a start on the VoteEngine !wip --- src/Ombi.Core/Engine/VoteEngine.cs | 96 ++++++++++++++++++++++++++ src/Ombi.Store/Context/IOmbiContext.cs | 1 + src/Ombi.Store/Context/OmbiContext.cs | 1 + src/Ombi.Store/Entities/Votes.cs | 25 +++++++ src/Ombi/Startup.cs | 2 + 5 files changed, 125 insertions(+) create mode 100644 src/Ombi.Core/Engine/VoteEngine.cs create mode 100644 src/Ombi.Store/Entities/Votes.cs diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs new file mode 100644 index 000000000..5c132075e --- /dev/null +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Ombi.Core.Authentication; +using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Rule.Interfaces; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; + +namespace Ombi.Core.Engine +{ + public class VoteEngine : BaseEngine + { + public VoteEngine(IRepository votes, IPrincipal user, OmbiUserManager um, IRuleEvaluator r) : base(user, um, r) + { + _voteRepository = votes; + } + + private readonly IRepository _voteRepository; + + public async Task GetVotesForMovie(int requestId) + { + return await _voteRepository.GetAll().FirstOrDefaultAsync(x => x.RequestType == RequestType.Movie && x.RequestId == requestId); + } + public IQueryable GetVotesForMovie(IEnumerable requestIds) + { + return _voteRepository.GetAll().Where(x => x.RequestType == RequestType.Movie && requestIds.Contains(x.RequestId)); + } + + public async Task GetVotesForTv(int requestId) + { + return await _voteRepository.GetAll().FirstOrDefaultAsync(x => x.RequestType == RequestType.TvShow && x.RequestId == requestId); + } + + public IQueryable GetVotesForTv(IEnumerable requestIds) + { + return _voteRepository.GetAll().Where(x => x.RequestType == RequestType.TvShow && requestIds.Contains(x.RequestId)); + } + + public async Task UpvoteMovie(int requestId) + { + var user = await GetUser(); + await _voteRepository.Add(new Votes + { + Date = DateTime.UtcNow, + RequestId = requestId, + RequestType = RequestType.Movie, + UserId = user.Id, + VoteType = VoteType.Upvote + }); + } + + public async Task DownvoteMovie(int requestId) + { + var user = await GetUser(); + await _voteRepository.Add(new Votes + { + Date = DateTime.UtcNow, + RequestId = requestId, + RequestType = RequestType.Movie, + UserId = user.Id, + VoteType = VoteType.Downvote + }); + } + + public async Task UpvoteTv(int requestId) + { + var user = await GetUser(); + await _voteRepository.Add(new Votes + { + Date = DateTime.UtcNow, + RequestId = requestId, + RequestType = RequestType.TvShow, + UserId = user.Id, + VoteType = VoteType.Upvote + }); + } + + public async Task DownvoteTv(int requestId) + { + var user = await GetUser(); + await _voteRepository.Add(new Votes + { + Date = DateTime.UtcNow, + RequestId = requestId, + RequestType = RequestType.TvShow, + UserId = user.Id, + VoteType = VoteType.Downvote + }); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Context/IOmbiContext.cs b/src/Ombi.Store/Context/IOmbiContext.cs index 55d7db563..03e528412 100644 --- a/src/Ombi.Store/Context/IOmbiContext.cs +++ b/src/Ombi.Store/Context/IOmbiContext.cs @@ -25,6 +25,7 @@ namespace Ombi.Store.Context DbSet Set() where TEntity : class; DbSet NotificationTemplates { get; set; } DbSet ApplicationConfigurations { get; set; } + DbSet Votes { get; set; } void Seed(); DbSet Audit { get; set; } DbSet MovieRequests { get; set; } diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index e4c9be516..6a408144f 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -39,6 +39,7 @@ namespace Ombi.Store.Context public DbSet IssueComments { get; set; } public DbSet RequestLogs { get; set; } public DbSet RecentlyAddedLogs { get; set; } + public DbSet Votes { get; set; } public DbSet Audit { get; set; } diff --git a/src/Ombi.Store/Entities/Votes.cs b/src/Ombi.Store/Entities/Votes.cs new file mode 100644 index 000000000..61e5651da --- /dev/null +++ b/src/Ombi.Store/Entities/Votes.cs @@ -0,0 +1,25 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Ombi.Store.Entities +{ + [Table("Votes")] + public class Votes : Entity + { + public int RequestId { get; set; } + public VoteType VoteType { get; set; } + public RequestType RequestType { get; set; } + public string UserId { get; set; } + public DateTime Date { get; set; } + public bool Deleted { get; set; } + + [ForeignKey(nameof(UserId))] + public OmbiUser User { get; set; } + } + + public enum VoteType + { + Upvote = 0, + Downvote = 1 + } +} \ No newline at end of file diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 1d7d67550..a3cb7f4be 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -169,6 +169,8 @@ namespace Ombi { // Generate a API Key settings.ApiKey = Guid.NewGuid().ToString("N"); + var userManager = app.ApplicationServices.GetService(); + userManager.CreateAsync(new OmbiUser {UserName = "API User", UserType = UserType.LocalUser}).Wait(); ombiService.SaveSettings(settings); } if (settings.BaseUrl.HasValue()) From 7aa2b72c7bd56c1e2f494a997a26679f2ad49f81 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 27 Sep 2018 13:25:06 +0100 Subject: [PATCH 02/46] Adding missing commits !wip --- src/Ombi.Schedule/JobSetup.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Schedule/JobSetup.cs b/src/Ombi.Schedule/JobSetup.cs index f82c96fba..7ce32de04 100644 --- a/src/Ombi.Schedule/JobSetup.cs +++ b/src/Ombi.Schedule/JobSetup.cs @@ -20,7 +20,8 @@ namespace Ombi.Schedule IOmbiAutomaticUpdater updater, IEmbyContentSync embySync, IPlexUserImporter userImporter, IEmbyUserImporter embyUserImporter, ISonarrSync cache, ICouchPotatoSync cpCache, ISettingsService jobsettings, ISickRageSync srSync, IRefreshMetadata refresh, - INewsletterJob newsletter, IPlexRecentlyAddedSync recentlyAddedPlex, ILidarrArtistSync artist) + INewsletterJob newsletter, IPlexRecentlyAddedSync recentlyAddedPlex, ILidarrArtistSync artist, + IIssuesPurge purge) { _plexContentSync = plexContentSync; _radarrSync = radarrSync; @@ -36,6 +37,7 @@ namespace Ombi.Schedule _newsletter = newsletter; _plexRecentlyAddedSync = recentlyAddedPlex; _lidarrArtistSync = artist; + _issuesPurge = purge; } private readonly IPlexContentSync _plexContentSync; @@ -52,6 +54,7 @@ namespace Ombi.Schedule private readonly IRefreshMetadata _refreshMetadata; private readonly INewsletterJob _newsletter; private readonly ILidarrArtistSync _lidarrArtistSync; + private readonly IIssuesPurge _issuesPurge; public void Setup() { @@ -66,6 +69,7 @@ namespace Ombi.Schedule RecurringJob.AddOrUpdate(() => _srSync.Start(), JobSettingsHelper.SickRageSync(s)); RecurringJob.AddOrUpdate(() => _refreshMetadata.Start(), JobSettingsHelper.RefreshMetadata(s)); RecurringJob.AddOrUpdate(() => _lidarrArtistSync.CacheContent(), JobSettingsHelper.LidarrArtistSync(s)); + RecurringJob.AddOrUpdate(() => _issuesPurge.Start(), JobSettingsHelper.IssuePurge(s)); RecurringJob.AddOrUpdate(() => _updater.Update(null), JobSettingsHelper.Updater(s)); From 66af4999706101a5275def1b1c2087dc67184d89 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 27 Sep 2018 13:26:41 +0100 Subject: [PATCH 03/46] Search for the Lidarr Album when it's a new artist. --- src/Ombi.Core/Senders/MusicSender.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs index 481fe4090..9e2dab1bd 100644 --- a/src/Ombi.Core/Senders/MusicSender.cs +++ b/src/Ombi.Core/Senders/MusicSender.cs @@ -76,7 +76,11 @@ namespace Ombi.Core.Senders var result = await _lidarrApi.AddArtist(newArtist, settings.ApiKey, settings.FullUri); if (result != null && result.id > 0) { - // Setup the albums + // Search for it + if (!settings.AddOnly) + { + await _lidarrApi.AlbumSearch(new[] { result.id }, settings.ApiKey, settings.FullUri); + } return new SenderResult { Message = "Album has been requested!", Sent = true, Success = true }; } } From b73bdec7899af053ff635d1975490550fbe81385 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Fri, 28 Sep 2018 10:31:50 +0100 Subject: [PATCH 04/46] Voting engine mostly done, adding tests for it !wip --- src/Ombi.Core.Tests/Engine/VoteEngineTests.cs | 57 ++++++++ src/Ombi.Core/Engine/VoteEngine.cs | 131 ++++++++++++------ src/Ombi.Core/Models/VoteEngineResult.cs | 10 ++ .../Settings/Models/VoteSettings.cs | 10 ++ 4 files changed, 168 insertions(+), 40 deletions(-) create mode 100644 src/Ombi.Core.Tests/Engine/VoteEngineTests.cs create mode 100644 src/Ombi.Core/Models/VoteEngineResult.cs create mode 100644 src/Ombi.Settings/Settings/Models/VoteSettings.cs diff --git a/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs new file mode 100644 index 000000000..3cb439a55 --- /dev/null +++ b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using Ombi.Core.Authentication; +using Ombi.Core.Engine; +using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models; +using Ombi.Store.Entities; +using Ombi.Store.Repository; + +namespace Ombi.Core.Tests.Engine +{ + [TestFixture] + public class VoteEngineTests + { + [SetUp] + public void Setup() + { + VoteRepository = new Mock>(); + VoteSettings = new Mock>(); + MusicRequestEngine = new Mock(); + TvRequestEngine = new Mock(); + MovieRequestEngine = new Mock(); + MovieRequestEngine = new Mock(); + User = new Mock(); + UserManager = new Mock(); + Rule = new Mock(); + Engine = new VoteEngine(VoteRepository.Object, User.Object, UserManager.Object, Rule.Object, VoteSettings.Object, MusicRequestEngine.Object, + TvRequestEngine.Object, MovieRequestEngine.Object); + } + + public VoteEngine Engine { get; set; } + public Mock User { get; set; } + public Mock UserManager { get; set; } + public Mock Rule { get; set; } + public Mock> VoteRepository { get; set; } + public Mock> VoteSettings { get; set; } + public Mock MusicRequestEngine { get; set; } + public Mock TvRequestEngine { get; set; } + public Mock MovieRequestEngine { get; set; } + + [Test] + public async Task New_Upvote() + { + var votes = new List(); + AutoFi + VoteRepository.Setup(x => x.GetAll()).Returns(new EnumerableQuery()) + var result = await Engine.UpVote(1, RequestType.Movie); + + } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs index 5c132075e..3c9b0faad 100644 --- a/src/Ombi.Core/Engine/VoteEngine.cs +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -6,91 +6,142 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Models; using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; -using Ombi.Store.Repository.Requests; namespace Ombi.Core.Engine { public class VoteEngine : BaseEngine { - public VoteEngine(IRepository votes, IPrincipal user, OmbiUserManager um, IRuleEvaluator r) : base(user, um, r) + public VoteEngine(IRepository votes, IPrincipal user, OmbiUserManager um, IRuleEvaluator r, ISettingsService voteSettings, + IMusicRequestEngine musicRequestEngine, ITvRequestEngine tvRequestEngine, IMovieRequestEngine movieRequestEngine) : base(user, um, r) { _voteRepository = votes; + _voteSettings = voteSettings; + _movieRequestEngine = movieRequestEngine; + _musicRequestEngine = musicRequestEngine; + _tvRequestEngine = tvRequestEngine; } private readonly IRepository _voteRepository; + private readonly ISettingsService _voteSettings; + private readonly IMusicRequestEngine _musicRequestEngine; + private readonly ITvRequestEngine _tvRequestEngine; + private readonly IMovieRequestEngine _movieRequestEngine; - public async Task GetVotesForMovie(int requestId) + public IQueryable GetVotes(int requestId, RequestType requestType) { - return await _voteRepository.GetAll().FirstOrDefaultAsync(x => x.RequestType == RequestType.Movie && x.RequestId == requestId); - } - public IQueryable GetVotesForMovie(IEnumerable requestIds) - { - return _voteRepository.GetAll().Where(x => x.RequestType == RequestType.Movie && requestIds.Contains(x.RequestId)); + return _voteRepository.GetAll().Where(x => x.RequestType == requestType && requestId == x.RequestId); } - public async Task GetVotesForTv(int requestId) + public Task GetVoteForUser(int requestId, string userId) { - return await _voteRepository.GetAll().FirstOrDefaultAsync(x => x.RequestType == RequestType.TvShow && x.RequestId == requestId); + return _voteRepository.GetAll().FirstOrDefaultAsync(x => x.RequestId == requestId && x.UserId == userId); } - public IQueryable GetVotesForTv(IEnumerable requestIds) + public async Task UpVote(int requestId, RequestType requestType) { - return _voteRepository.GetAll().Where(x => x.RequestType == RequestType.TvShow && requestIds.Contains(x.RequestId)); - } + // How many votes does this have?! + var currentVotes = GetVotes(requestId, requestType); + var voteSettings = await _voteSettings.GetSettingsAsync(); - public async Task UpvoteMovie(int requestId) - { + // Does this user have a downvote? If so we should revert it and make it an upvote var user = await GetUser(); + + var currentVote = await GetVoteForUser(requestId, user.Id); + if (currentVote != null && currentVote.VoteType == VoteType.Upvote) + { + return new VoteEngineResult { ErrorMessage = "You have already voted!" }; + } + await RemoveCurrentVote(currentVote); + await _voteRepository.Add(new Votes { Date = DateTime.UtcNow, RequestId = requestId, - RequestType = RequestType.Movie, + RequestType = requestType, UserId = user.Id, VoteType = VoteType.Upvote }); + + var upVotes = await currentVotes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); + var downVotes = -(await currentVotes.Where(x => x.VoteType == VoteType.Downvote).CountAsync()); + + var totalVotes = upVotes + downVotes; + RequestEngineResult result = null; + switch (requestType) + { + case RequestType.TvShow: + if (totalVotes >= voteSettings.TvShowVoteMax) + { + result = await _tvRequestEngine.ApproveChildRequest(requestId); + } + break; + case RequestType.Movie: + if (totalVotes >= voteSettings.MovieVoteMax) + { + result = await _movieRequestEngine.ApproveMovieById(requestId); + } + break; + case RequestType.Album: + if (totalVotes >= voteSettings.MusicVoteMax) + { + result = await _musicRequestEngine.ApproveAlbumById(requestId); + } + break; + default: + throw new ArgumentOutOfRangeException(nameof(requestType), requestType, null); + } + + if (result != null && !result.Result) + { + return new VoteEngineResult + { + ErrorMessage = "Voted succesfully but could not approve movie!" + }; + } + + return new VoteEngineResult + { + Result = true + }; } - public async Task DownvoteMovie(int requestId) + public async Task DownVote(int requestId, RequestType requestType) { var user = await GetUser(); + var currentVote = await GetVoteForUser(requestId, user.Id); + if (currentVote != null && currentVote.VoteType == VoteType.Upvote) + { + return new VoteEngineResult { ErrorMessage = "You have already voted!" }; + } + await RemoveCurrentVote(currentVote); + await _voteRepository.Add(new Votes { Date = DateTime.UtcNow, RequestId = requestId, - RequestType = RequestType.Movie, + RequestType = requestType, UserId = user.Id, VoteType = VoteType.Downvote }); + + return new VoteEngineResult + { + Result = true + }; } - public async Task UpvoteTv(int requestId) + public async Task RemoveCurrentVote(Votes currentVote) { - var user = await GetUser(); - await _voteRepository.Add(new Votes + if (currentVote != null) { - Date = DateTime.UtcNow, - RequestId = requestId, - RequestType = RequestType.TvShow, - UserId = user.Id, - VoteType = VoteType.Upvote - }); - } - - public async Task DownvoteTv(int requestId) - { - var user = await GetUser(); - await _voteRepository.Add(new Votes - { - Date = DateTime.UtcNow, - RequestId = requestId, - RequestType = RequestType.TvShow, - UserId = user.Id, - VoteType = VoteType.Downvote - }); + await _voteRepository.Delete(currentVote); + } } } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/VoteEngineResult.cs b/src/Ombi.Core/Models/VoteEngineResult.cs new file mode 100644 index 000000000..7546b0bb2 --- /dev/null +++ b/src/Ombi.Core/Models/VoteEngineResult.cs @@ -0,0 +1,10 @@ +namespace Ombi.Core.Models +{ + public class VoteEngineResult + { + public bool Result { get; set; } + public string Message { get; set; } + public bool IsError => !string.IsNullOrEmpty(ErrorMessage); + public string ErrorMessage { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/VoteSettings.cs b/src/Ombi.Settings/Settings/Models/VoteSettings.cs new file mode 100644 index 000000000..4d63cfea4 --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/VoteSettings.cs @@ -0,0 +1,10 @@ +namespace Ombi.Settings.Settings.Models +{ + public class VoteSettings : Settings + { + public bool Enabled { get; set; } + public int MovieVoteMax { get; set; } + public int MusicVoteMax { get; set; } + public int TvShowVoteMax { get; set; } + } +} \ No newline at end of file From eb89b352f49e278f6a42a52b138114d55a47b794 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Fri, 28 Sep 2018 10:33:56 +0100 Subject: [PATCH 05/46] Updated test dependancies --- src/Ombi.Core.Tests/Ombi.Core.Tests.csproj | 4 ++-- .../Ombi.Notifications.Tests.csproj | 8 ++++---- src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj | 4 ++-- src/Ombi.Tests/Ombi.Tests.csproj | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj index 30de4b6f0..dcaf7a365 100644 --- a/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj +++ b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj @@ -5,9 +5,9 @@ - + - + diff --git a/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj b/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj index de1c55533..5d5d3b9d0 100644 --- a/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj +++ b/src/Ombi.Notifications.Tests/Ombi.Notifications.Tests.csproj @@ -5,11 +5,11 @@ - - - + + + - + diff --git a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj index ea1d17f8c..ca07f635f 100644 --- a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj +++ b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj @@ -6,9 +6,9 @@ - + - + diff --git a/src/Ombi.Tests/Ombi.Tests.csproj b/src/Ombi.Tests/Ombi.Tests.csproj index 95eb09353..55c66b80c 100644 --- a/src/Ombi.Tests/Ombi.Tests.csproj +++ b/src/Ombi.Tests/Ombi.Tests.csproj @@ -8,10 +8,10 @@ - - - - + + + + From 2f964f904e881031617350a18b7b1b497ac74060 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Fri, 28 Sep 2018 12:50:57 +0100 Subject: [PATCH 06/46] Moar !wip --- src/Ombi.Core.Tests/Engine/VoteEngineTests.cs | 22 ++++++-- src/Ombi.Core.Tests/Ombi.Core.Tests.csproj | 1 + src/Ombi.Core/Engine/IVoteEngine.cs | 16 ++++++ src/Ombi.Core/Engine/Interfaces/BaseEngine.cs | 3 -- src/Ombi.Core/Engine/TvSearchEngine.cs | 16 +++--- src/Ombi.Core/Engine/VoteEngine.cs | 13 ++++- src/Ombi.DependencyInjection/IocExtensions.cs | 1 + src/Ombi/Controllers/VoteController.cs | 53 +++++++++++++++++++ 8 files changed, 109 insertions(+), 16 deletions(-) create mode 100644 src/Ombi.Core/Engine/IVoteEngine.cs create mode 100644 src/Ombi/Controllers/VoteController.cs diff --git a/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs index 3cb439a55..ad4c33131 100644 --- a/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Security.Principal; using System.Threading.Tasks; +using AutoFixture; using Moq; using NUnit.Framework; using Ombi.Core.Authentication; @@ -21,6 +22,7 @@ namespace Ombi.Core.Tests.Engine [SetUp] public void Setup() { + F = new Fixture(); VoteRepository = new Mock>(); VoteSettings = new Mock>(); MusicRequestEngine = new Mock(); @@ -29,11 +31,14 @@ namespace Ombi.Core.Tests.Engine MovieRequestEngine = new Mock(); User = new Mock(); UserManager = new Mock(); + UserManager.Setup(x => x.Users) + .Returns(new EnumerableQuery(new List {new OmbiUser {Id = "abc"}})); Rule = new Mock(); Engine = new VoteEngine(VoteRepository.Object, User.Object, UserManager.Object, Rule.Object, VoteSettings.Object, MusicRequestEngine.Object, TvRequestEngine.Object, MovieRequestEngine.Object); } + public Fixture F { get; set; } public VoteEngine Engine { get; set; } public Mock User { get; set; } public Mock UserManager { get; set; } @@ -45,13 +50,24 @@ namespace Ombi.Core.Tests.Engine public Mock MovieRequestEngine { get; set; } [Test] + [Ignore("Need to mock the user manager")] public async Task New_Upvote() { - var votes = new List(); - AutoFi - VoteRepository.Setup(x => x.GetAll()).Returns(new EnumerableQuery()) + VoteSettings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new VoteSettings()); + var votes = F.CreateMany().ToList(); + votes.Add(new Votes + { + RequestId = 1, + RequestType = RequestType.Movie, + UserId = "abc" + }); + VoteRepository.Setup(x => x.GetAll()).Returns(new EnumerableQuery(votes)); var result = await Engine.UpVote(1, RequestType.Movie); + Assert.That(result.Result, Is.True); + VoteRepository.Verify(x => x.Add(It.Is(c => c.UserId == "abc" && c.VoteType == VoteType.Upvote)), Times.Once); + VoteRepository.Verify(x => x.Delete(It.IsAny()), Times.Once); + MovieRequestEngine.Verify(x => x.ApproveMovieById(1), Times.Never); } } } \ No newline at end of file diff --git a/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj index dcaf7a365..d20176ec4 100644 --- a/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj +++ b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj @@ -5,6 +5,7 @@ + diff --git a/src/Ombi.Core/Engine/IVoteEngine.cs b/src/Ombi.Core/Engine/IVoteEngine.cs new file mode 100644 index 000000000..45b0761a4 --- /dev/null +++ b/src/Ombi.Core/Engine/IVoteEngine.cs @@ -0,0 +1,16 @@ +using System.Linq; +using System.Threading.Tasks; +using Ombi.Core.Models; +using Ombi.Store.Entities; + +namespace Ombi.Core.Engine +{ + public interface IVoteEngine + { + Task DownVote(int requestId, RequestType requestType); + Task GetVoteForUser(int requestId, string userId); + IQueryable GetVotes(int requestId, RequestType requestType); + Task RemoveCurrentVote(Votes currentVote); + Task UpVote(int requestId, RequestType requestType); + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs index 26bc5969c..c5cb8c45a 100644 --- a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs @@ -7,11 +7,8 @@ using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; using Ombi.Store.Entities.Requests; using Ombi.Store.Entities; -using Microsoft.AspNetCore.Identity; -using System.Linq; using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; -using Ombi.Helpers; namespace Ombi.Core.Engine.Interfaces { diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs index bb674a35d..c8e958002 100644 --- a/src/Ombi.Core/Engine/TvSearchEngine.cs +++ b/src/Ombi.Core/Engine/TvSearchEngine.cs @@ -61,7 +61,7 @@ namespace Ombi.Core.Engine { continue; } - retVal.Add(await ProcessResult(tvMazeSearch)); + retVal.Add(ProcessResult(tvMazeSearch)); } return retVal; } @@ -123,7 +123,7 @@ namespace Ombi.Core.Engine public async Task> Popular() { var result = await Cache.GetOrAdd(CacheKeys.PopularTv, async () => await TraktApi.GetPopularShows(), DateTime.Now.AddHours(12)); - var processed = await ProcessResults(result); + var processed = ProcessResults(result); return processed; } @@ -131,35 +131,35 @@ namespace Ombi.Core.Engine { var result = await Cache.GetOrAdd(CacheKeys.AnticipatedTv, async () => await TraktApi.GetAnticipatedShows(), DateTime.Now.AddHours(12)); - var processed = await ProcessResults(result); + var processed = ProcessResults(result); return processed; } public async Task> MostWatches() { var result = await Cache.GetOrAdd(CacheKeys.MostWatchesTv, async () => await TraktApi.GetMostWatchesShows(), DateTime.Now.AddHours(12)); - var processed = await ProcessResults(result); + var processed = ProcessResults(result); return processed; } public async Task> Trending() { var result = await Cache.GetOrAdd(CacheKeys.TrendingTv, async () => await TraktApi.GetTrendingShows(), DateTime.Now.AddHours(12)); - var processed = await ProcessResults(result); + var processed = ProcessResults(result); return processed; } - private async Task> ProcessResults(IEnumerable items) + private IEnumerable ProcessResults(IEnumerable items) { var retVal = new List(); foreach (var tvMazeSearch in items) { - retVal.Add(await ProcessResult(tvMazeSearch)); + retVal.Add(ProcessResult(tvMazeSearch)); } return retVal; } - private async Task ProcessResult(T tvMazeSearch) + private SearchTvShowViewModel ProcessResult(T tvMazeSearch) { return Mapper.Map(tvMazeSearch); } diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs index 3c9b0faad..5bf8549e1 100644 --- a/src/Ombi.Core/Engine/VoteEngine.cs +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Security.Principal; using System.Threading.Tasks; @@ -15,7 +14,7 @@ using Ombi.Store.Repository; namespace Ombi.Core.Engine { - public class VoteEngine : BaseEngine + public class VoteEngine : BaseEngine, IVoteEngine { public VoteEngine(IRepository votes, IPrincipal user, OmbiUserManager um, IRuleEvaluator r, ISettingsService voteSettings, IMusicRequestEngine musicRequestEngine, ITvRequestEngine tvRequestEngine, IMovieRequestEngine movieRequestEngine) : base(user, um, r) @@ -33,6 +32,16 @@ namespace Ombi.Core.Engine private readonly ITvRequestEngine _tvRequestEngine; private readonly IMovieRequestEngine _movieRequestEngine; + public async Task GetMovieViewModel() + { + var requests = await _movieRequestEngine.GetRequests(); + foreach (var r in requests) + { + // Make model + var votes = GetVotes(r.Id, RequestType.Movie); + } + } + public IQueryable GetVotes(int requestId, RequestType requestType) { return _voteRepository.GetAll().Where(x => x.RequestType == requestType && requestId == x.RequestId); diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 3af06b476..30ccb6973 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -91,6 +91,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } public static void RegisterHttp(this IServiceCollection services) { diff --git a/src/Ombi/Controllers/VoteController.cs b/src/Ombi/Controllers/VoteController.cs new file mode 100644 index 000000000..5039626be --- /dev/null +++ b/src/Ombi/Controllers/VoteController.cs @@ -0,0 +1,53 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Ombi.Core.Engine; +using Ombi.Store.Entities; + +namespace Ombi.Controllers +{ + [ApiV1] + [Authorize] + [Produces("application/json")] + public class VoteController : Controller + { + public VoteController(IVoteEngine engine) + { + _engine = engine; + } + + private readonly IVoteEngine _engine; + + /// + /// Get's all the votes for the request id + /// + /// + [HttpGet("movie/{requestId:int}")] + public Task> MovieVotes(int requestId) + { + return _engine.GetVotes(requestId, RequestType.Movie).ToListAsync(); + } + + /// + /// Get's all the votes for the request id + /// + /// + [HttpGet("music/{requestId:int}")] + public Task> MusicVotes(int requestId) + { + return _engine.GetVotes(requestId, RequestType.Album).ToListAsync(); + } + + /// + /// Get's all the votes for the request id + /// + /// + [HttpGet("tv/{requestId:int}")] + public Task> TvVotes(int requestId) + { + return _engine.GetVotes(requestId, RequestType.TvShow).ToListAsync(); + } + } +} \ No newline at end of file From cfd0625df4998fdb497cd1ee83a2bac10a38ebb9 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Fri, 28 Sep 2018 12:56:23 +0100 Subject: [PATCH 07/46] !wip --- src/Ombi.Core/Engine/VoteEngine.cs | 24 +++++++++++++++++++++--- src/Ombi.Core/Models/UI/VoteViewModel.cs | 16 ++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 src/Ombi.Core/Models/UI/VoteViewModel.cs diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs index 5bf8549e1..ecd22e848 100644 --- a/src/Ombi.Core/Engine/VoteEngine.cs +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Security.Principal; using System.Threading.Tasks; @@ -6,6 +7,7 @@ using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; using Ombi.Core.Engine.Interfaces; using Ombi.Core.Models; +using Ombi.Core.Models.UI; using Ombi.Core.Rule.Interfaces; using Ombi.Core.Settings; using Ombi.Settings.Settings.Models; @@ -32,14 +34,30 @@ namespace Ombi.Core.Engine private readonly ITvRequestEngine _tvRequestEngine; private readonly IMovieRequestEngine _movieRequestEngine; - public async Task GetMovieViewModel() + public async Task> GetMovieViewModel() { - var requests = await _movieRequestEngine.GetRequests(); - foreach (var r in requests) + var vm = new List(); + var movieRequests = await _movieRequestEngine.GetRequests(); + foreach (var r in movieRequests) { // Make model var votes = GetVotes(r.Id, RequestType.Movie); + var upVotes = await votes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); + var downVotes = await votes.Where(x => x.VoteType == VoteType.Downvote).CountAsync(); + vm.Add(new VoteViewModel + { + Upvotes = upVotes, + Downvotes = downVotes, + RequestId = r.Id, + RequestType = RequestType.Movie, + Title = r.Title, + Image = r.PosterPath, + Background = r.Background, + Description = r.Overview + }); } + + return vm; } public IQueryable GetVotes(int requestId, RequestType requestType) diff --git a/src/Ombi.Core/Models/UI/VoteViewModel.cs b/src/Ombi.Core/Models/UI/VoteViewModel.cs new file mode 100644 index 000000000..71d6c95a9 --- /dev/null +++ b/src/Ombi.Core/Models/UI/VoteViewModel.cs @@ -0,0 +1,16 @@ +using Ombi.Store.Entities; + +namespace Ombi.Core.Models.UI +{ + public class VoteViewModel + { + public int RequestId { get; set; } + public RequestType RequestType { get; set; } + public string Image { get; set; } + public string Background { get; set; } + public int Upvotes { get; set; } + public int Downvotes { get; set; } + public string Title { get; set; } + public string Description { get; set; } + } +} \ No newline at end of file From d19efd91a5f7dda342aec77f74d575fe6a886bf5 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 28 Sep 2018 20:35:16 +0100 Subject: [PATCH 08/46] Put the issue purge limit on the issues page --- .../app/settings/issues/issues.component.html | 13 +++++++------ .../app/settings/issues/issues.component.ts | 5 +++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Ombi/ClientApp/app/settings/issues/issues.component.html b/src/Ombi/ClientApp/app/settings/issues/issues.component.html index ee780a1a1..fa5988a79 100644 --- a/src/Ombi/ClientApp/app/settings/issues/issues.component.html +++ b/src/Ombi/ClientApp/app/settings/issues/issues.component.html @@ -26,12 +26,13 @@
-
- - -
+ +
+
@@ -52,8 +53,8 @@
- +
diff --git a/src/Ombi/ClientApp/app/settings/issues/issues.component.ts b/src/Ombi/ClientApp/app/settings/issues/issues.component.ts index 37ead870a..cfe0bd65c 100644 --- a/src/Ombi/ClientApp/app/settings/issues/issues.component.ts +++ b/src/Ombi/ClientApp/app/settings/issues/issues.component.ts @@ -55,6 +55,11 @@ export class IssuesComponent implements OnInit { const settings = form.value; + if(settings.deleteIssues && settings.daysAfterResolvedToDelete <= 0) { + this.notificationService.error("You need to enter days greater than 0"); + return; + } + this.settingsService.saveIssueSettings(settings).subscribe(x => { if (x) { this.notificationService.success("Successfully saved the Issue settings"); From 3f7eb804709e7447a05a5e26b0a81de148190358 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 28 Sep 2018 21:00:05 +0100 Subject: [PATCH 09/46] !wip done api --- src/Ombi.Core/Engine/IVoteEngine.cs | 5 +- src/Ombi.Core/Engine/VoteEngine.cs | 54 ++++++++++++++++++++ src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 4 +- src/Ombi/Controllers/VoteController.cs | 7 +++ 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Core/Engine/IVoteEngine.cs b/src/Ombi.Core/Engine/IVoteEngine.cs index 45b0761a4..681f333c5 100644 --- a/src/Ombi.Core/Engine/IVoteEngine.cs +++ b/src/Ombi.Core/Engine/IVoteEngine.cs @@ -1,6 +1,8 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Ombi.Core.Models; +using Ombi.Core.Models.UI; using Ombi.Store.Entities; namespace Ombi.Core.Engine @@ -12,5 +14,6 @@ namespace Ombi.Core.Engine IQueryable GetVotes(int requestId, RequestType requestType); Task RemoveCurrentVote(Votes currentVote); Task UpVote(int requestId, RequestType requestType); + Task> GetMovieViewModel(); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs index ecd22e848..3875b6705 100644 --- a/src/Ombi.Core/Engine/VoteEngine.cs +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Security.Principal; +using System.Text; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Ombi.Core.Authentication; @@ -10,6 +11,7 @@ using Ombi.Core.Models; using Ombi.Core.Models.UI; using Ombi.Core.Rule.Interfaces; using Ombi.Core.Settings; +using Ombi.Schedule.Jobs.Ombi; using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; @@ -38,6 +40,8 @@ namespace Ombi.Core.Engine { var vm = new List(); var movieRequests = await _movieRequestEngine.GetRequests(); + var tvRequestsTask = _tvRequestEngine.GetRequestsLite(); + var musicRequestsTask = _musicRequestEngine.GetRequests(); foreach (var r in movieRequests) { // Make model @@ -57,6 +61,56 @@ namespace Ombi.Core.Engine }); } + foreach (var r in await musicRequestsTask) + { + // Make model + var votes = GetVotes(r.Id, RequestType.Movie); + var upVotes = await votes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); + var downVotes = await votes.Where(x => x.VoteType == VoteType.Downvote).CountAsync(); + vm.Add(new VoteViewModel + { + Upvotes = upVotes, + Downvotes = downVotes, + RequestId = r.Id, + RequestType = RequestType.Movie, + Title = r.Title, + Image = r.Disk, + Background = r.Cover, + Description = r.ArtistName + }); + } + + foreach (var r in await tvRequestsTask) + { + // Make model + var votes = GetVotes(r.Id, RequestType.Movie); + var upVotes = await votes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); + var downVotes = await votes.Where(x => x.VoteType == VoteType.Downvote).CountAsync(); + + var finalsb = new StringBuilder(); + foreach (var childRequests in r.ChildRequests) + { + foreach (var epInformation in childRequests.SeasonRequests.OrderBy(x => x.SeasonNumber)) + { + var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); + var episodeString = NewsletterJob.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); + finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString}"); + finalsb.Append("
"); + } + } + vm.Add(new VoteViewModel + { + Upvotes = upVotes, + Downvotes = downVotes, + RequestId = r.Id, + RequestType = RequestType.Movie, + Title = r.Title, + Image = r.PosterPath, + Background = r.Background, + Description = finalsb.ToString() + }); + } + return vm; } diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index f152f6b4b..9f5e58482 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -654,7 +654,7 @@ namespace Ombi.Schedule.Jobs.Ombi AddInfoTable(sb); var title = ""; - if (!String.IsNullOrEmpty(info.premiered) && info.premiered.Length > 4) + if (!string.IsNullOrEmpty(info.premiered) && info.premiered.Length > 4) { title = $"{t.Title} ({info.premiered.Remove(4)})"; } else @@ -715,7 +715,7 @@ namespace Ombi.Schedule.Jobs.Ombi } } - public string BuildEpisodeList(IEnumerable orderedEpisodes) + public static string BuildEpisodeList(IEnumerable orderedEpisodes) { var epSb = new StringBuilder(); var previousEpisodes = new List(); diff --git a/src/Ombi/Controllers/VoteController.cs b/src/Ombi/Controllers/VoteController.cs index 5039626be..f1466e3ed 100644 --- a/src/Ombi/Controllers/VoteController.cs +++ b/src/Ombi/Controllers/VoteController.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using Microsoft.EntityFrameworkCore; using Ombi.Core.Engine; +using Ombi.Core.Models.UI; using Ombi.Store.Entities; namespace Ombi.Controllers @@ -20,6 +21,12 @@ namespace Ombi.Controllers private readonly IVoteEngine _engine; + [HttpGet] + public Task> GetView() + { + return _engine.GetMovieViewModel(); + } + /// /// Get's all the votes for the request id /// From bb4d59e35588a7ad4bc9818d14c8102b65416e16 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 28 Sep 2018 21:02:30 +0100 Subject: [PATCH 10/46] Removed the pinID from the OAuth url #2548 --- src/Ombi.Api.Plex/IPlexApi.cs | 2 +- src/Ombi.Api.Plex/PlexApi.cs | 3 +-- src/Ombi.Core/Authentication/PlexOAuthManager.cs | 8 ++++---- src/Ombi.Core/IPlexOAuthManager.cs | 4 ++-- src/Ombi/Controllers/External/PlexController.cs | 4 ++-- src/Ombi/Controllers/TokenController.cs | 2 +- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/Ombi.Api.Plex/IPlexApi.cs b/src/Ombi.Api.Plex/IPlexApi.cs index 343eaa2d7..c79ec50c9 100644 --- a/src/Ombi.Api.Plex/IPlexApi.cs +++ b/src/Ombi.Api.Plex/IPlexApi.cs @@ -24,7 +24,7 @@ namespace Ombi.Api.Plex Task GetAccount(string authToken); Task GetRecentlyAdded(string authToken, string uri, string sectionId); Task GetPin(int pinId); - Task GetOAuthUrl(int pinId, string code, string applicationUrl); + Task GetOAuthUrl(string code, string applicationUrl); Task AddUser(string emailAddress, string serverId, string authToken, int[] libs); } } \ No newline at end of file diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index f0808622f..fe6ba23e2 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -217,12 +217,11 @@ namespace Ombi.Api.Plex return await Api.Request(request); } - public async Task GetOAuthUrl(int pinId, string code, string applicationUrl) + public async Task GetOAuthUrl(string code, string applicationUrl) { var request = new Request("auth#", "https://app.plex.tv", HttpMethod.Get); await AddHeaders(request); - request.AddQueryString("pinID", pinId.ToString()); request.AddQueryString("code", code); request.AddQueryString("context[device][product]", ApplicationName); request.AddQueryString("context[device][environment]", "bundled"); diff --git a/src/Ombi.Core/Authentication/PlexOAuthManager.cs b/src/Ombi.Core/Authentication/PlexOAuthManager.cs index 426037bb7..76b1b5d97 100644 --- a/src/Ombi.Core/Authentication/PlexOAuthManager.cs +++ b/src/Ombi.Core/Authentication/PlexOAuthManager.cs @@ -36,17 +36,17 @@ namespace Ombi.Core.Authentication return await _api.GetAccount(accessToken); } - public async Task GetOAuthUrl(int pinId, string code, string websiteAddress = null) + public async Task GetOAuthUrl(string code, string websiteAddress = null) { var settings = await _customizationSettingsService.GetSettingsAsync(); - var url = await _api.GetOAuthUrl(pinId, code, settings.ApplicationUrl.IsNullOrEmpty() ? websiteAddress : settings.ApplicationUrl); + var url = await _api.GetOAuthUrl(code, settings.ApplicationUrl.IsNullOrEmpty() ? websiteAddress : settings.ApplicationUrl); return url; } - public async Task GetWizardOAuthUrl(int pinId, string code, string websiteAddress) + public async Task GetWizardOAuthUrl(string code, string websiteAddress) { - var url = await _api.GetOAuthUrl(pinId, code, websiteAddress); + var url = await _api.GetOAuthUrl(code, websiteAddress); return url; } } diff --git a/src/Ombi.Core/IPlexOAuthManager.cs b/src/Ombi.Core/IPlexOAuthManager.cs index a5c0c44ff..7668ee882 100644 --- a/src/Ombi.Core/IPlexOAuthManager.cs +++ b/src/Ombi.Core/IPlexOAuthManager.cs @@ -7,8 +7,8 @@ namespace Ombi.Core.Authentication public interface IPlexOAuthManager { Task GetAccessTokenFromPin(int pinId); - Task GetOAuthUrl(int pinId, string code, string websiteAddress = null); - Task GetWizardOAuthUrl(int pinId, string code, string websiteAddress); + Task GetOAuthUrl(string code, string websiteAddress = null); + Task GetWizardOAuthUrl(string code, string websiteAddress); Task GetAccount(string accessToken); } } \ No newline at end of file diff --git a/src/Ombi/Controllers/External/PlexController.cs b/src/Ombi/Controllers/External/PlexController.cs index d7cefd091..f0492b580 100644 --- a/src/Ombi/Controllers/External/PlexController.cs +++ b/src/Ombi/Controllers/External/PlexController.cs @@ -283,12 +283,12 @@ namespace Ombi.Controllers.External Uri url; if (!wizard.Wizard) { - url = await _plexOAuthManager.GetOAuthUrl(wizard.Pin.id, wizard.Pin.code); + url = await _plexOAuthManager.GetOAuthUrl(wizard.Pin.code); } else { var websiteAddress =$"{this.Request.Scheme}://{this.Request.Host}{this.Request.PathBase}"; - url = await _plexOAuthManager.GetWizardOAuthUrl(wizard.Pin.id, wizard.Pin.code, websiteAddress); + url = await _plexOAuthManager.GetWizardOAuthUrl(wizard.Pin.code, websiteAddress); } if (url == null) diff --git a/src/Ombi/Controllers/TokenController.cs b/src/Ombi/Controllers/TokenController.cs index 1314a741a..87136fd00 100644 --- a/src/Ombi/Controllers/TokenController.cs +++ b/src/Ombi/Controllers/TokenController.cs @@ -83,7 +83,7 @@ namespace Ombi.Controllers var websiteAddress = $"{this.Request.Scheme}://{this.Request.Host}{this.Request.PathBase}"; //https://app.plex.tv/auth#?forwardUrl=http://google.com/&clientID=Ombi-Test&context%5Bdevice%5D%5Bproduct%5D=Ombi%20SSO&pinID=798798&code=4lgfd - var url = await _plexOAuthManager.GetOAuthUrl(model.PlexTvPin.id, model.PlexTvPin.code, websiteAddress); + var url = await _plexOAuthManager.GetOAuthUrl(model.PlexTvPin.code, websiteAddress); if (url == null) { return new JsonResult(new From 660df9912315a4679656c18a86b9a75a32fc350d Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 28 Sep 2018 23:21:01 +0100 Subject: [PATCH 11/46] Got most of the UI done for the voting feature !wip --- src/Ombi.Core/Engine/VoteEngine.cs | 16 +- src/Ombi.Schedule.Tests/NewsletterTests.cs | 14 +- .../20180928201334_Votes.Designer.cs | 1182 +++++++++++++++++ .../Migrations/20180928201334_Votes.cs | 46 + .../Migrations/OmbiContextModelSnapshot.cs | 31 + src/Ombi/ClientApp/app/app.module.ts | 4 +- .../ClientApp/app/interfaces/IRequestModel.ts | 1 + src/Ombi/ClientApp/app/interfaces/IVote.ts | 23 + src/Ombi/ClientApp/app/interfaces/index.ts | 1 + src/Ombi/ClientApp/app/services/index.ts | 1 + .../ClientApp/app/services/vote.service.ts | 36 + .../ClientApp/app/vote/vote.component.html | 35 + .../ClientApp/app/vote/vote.component.scss | 12 + src/Ombi/ClientApp/app/vote/vote.component.ts | 70 + src/Ombi/ClientApp/app/vote/vote.module.ts | 41 + src/Ombi/ClientApp/styles/base.scss | 3 +- src/Ombi/Controllers/VoteController.cs | 58 + 17 files changed, 1551 insertions(+), 23 deletions(-) create mode 100644 src/Ombi.Store/Migrations/20180928201334_Votes.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20180928201334_Votes.cs create mode 100644 src/Ombi/ClientApp/app/interfaces/IVote.ts create mode 100644 src/Ombi/ClientApp/app/services/vote.service.ts create mode 100644 src/Ombi/ClientApp/app/vote/vote.component.html create mode 100644 src/Ombi/ClientApp/app/vote/vote.component.scss create mode 100644 src/Ombi/ClientApp/app/vote/vote.component.ts create mode 100644 src/Ombi/ClientApp/app/vote/vote.module.ts diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs index 3875b6705..8f70a1ed5 100644 --- a/src/Ombi.Core/Engine/VoteEngine.cs +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -40,7 +40,7 @@ namespace Ombi.Core.Engine { var vm = new List(); var movieRequests = await _movieRequestEngine.GetRequests(); - var tvRequestsTask = _tvRequestEngine.GetRequestsLite(); + var tvRequestsTask = _tvRequestEngine.GetRequests(); var musicRequestsTask = _musicRequestEngine.GetRequests(); foreach (var r in movieRequests) { @@ -55,8 +55,8 @@ namespace Ombi.Core.Engine RequestId = r.Id, RequestType = RequestType.Movie, Title = r.Title, - Image = r.PosterPath, - Background = r.Background, + Image = $"https://image.tmdb.org/t/p/w500/{r.PosterPath}", + Background = $"https://image.tmdb.org/t/p/w1280{r.Background}", Description = r.Overview }); } @@ -64,7 +64,7 @@ namespace Ombi.Core.Engine foreach (var r in await musicRequestsTask) { // Make model - var votes = GetVotes(r.Id, RequestType.Movie); + var votes = GetVotes(r.Id, RequestType.Album); var upVotes = await votes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); var downVotes = await votes.Where(x => x.VoteType == VoteType.Downvote).CountAsync(); vm.Add(new VoteViewModel @@ -72,9 +72,9 @@ namespace Ombi.Core.Engine Upvotes = upVotes, Downvotes = downVotes, RequestId = r.Id, - RequestType = RequestType.Movie, + RequestType = RequestType.Album, Title = r.Title, - Image = r.Disk, + Image = r.Cover, Background = r.Cover, Description = r.ArtistName }); @@ -83,7 +83,7 @@ namespace Ombi.Core.Engine foreach (var r in await tvRequestsTask) { // Make model - var votes = GetVotes(r.Id, RequestType.Movie); + var votes = GetVotes(r.Id, RequestType.TvShow); var upVotes = await votes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); var downVotes = await votes.Where(x => x.VoteType == VoteType.Downvote).CountAsync(); @@ -103,7 +103,7 @@ namespace Ombi.Core.Engine Upvotes = upVotes, Downvotes = downVotes, RequestId = r.Id, - RequestType = RequestType.Movie, + RequestType = RequestType.TvShow, Title = r.Title, Image = r.PosterPath, Background = r.Background, diff --git a/src/Ombi.Schedule.Tests/NewsletterTests.cs b/src/Ombi.Schedule.Tests/NewsletterTests.cs index b3c2ce98a..146cd97cf 100644 --- a/src/Ombi.Schedule.Tests/NewsletterTests.cs +++ b/src/Ombi.Schedule.Tests/NewsletterTests.cs @@ -1,11 +1,6 @@ using System.Collections.Generic; -using Moq; using NUnit.Framework; -using Ombi.Core.Settings; -using Ombi.Schedule.Jobs.Ombi; -using Ombi.Settings.Settings.Models; -using Ombi.Settings.Settings.Models.Notifications; -using Ombi.Store.Entities; +using static Ombi.Schedule.Jobs.Ombi.NewsletterJob; namespace Ombi.Schedule.Tests { @@ -15,17 +10,12 @@ namespace Ombi.Schedule.Tests [TestCaseSource(nameof(EpisodeListData))] public string BuildEpisodeListTest(List episodes) { - var emailSettings = new Mock>(); - var customziation = new Mock>(); - var newsletterSettings = new Mock>(); - var newsletter = new NewsletterJob(null, null, null, null, null, null, customziation.Object, emailSettings.Object, null, null, newsletterSettings.Object, null, null, null, null); - var ep = new List(); foreach (var i in episodes) { ep.Add(i); } - var result = newsletter.BuildEpisodeList(ep); + var result = BuildEpisodeList(ep); return result; } diff --git a/src/Ombi.Store/Migrations/20180928201334_Votes.Designer.cs b/src/Ombi.Store/Migrations/20180928201334_Votes.Designer.cs new file mode 100644 index 000000000..5d9b47c26 --- /dev/null +++ b/src/Ombi.Store/Migrations/20180928201334_Votes.Designer.cs @@ -0,0 +1,1182 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; + +namespace Ombi.Store.Migrations +{ + [DbContext(typeof(OmbiContext))] + [Migration("20180928201334_Votes")] + partial class Votes + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("UserType"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RadarrQualityProfile"); + + b.Property("RadarrRootPath"); + + b.Property("SonarrQualityProfile"); + + b.Property("SonarrQualityProfileAnime"); + + b.Property("SonarrRootPath"); + + b.Property("SonarrRootPathAnime"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Date"); + + b.Property("Deleted"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.Property("VoteType"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/20180928201334_Votes.cs b/src/Ombi.Store/Migrations/20180928201334_Votes.cs new file mode 100644 index 000000000..1c64a19aa --- /dev/null +++ b/src/Ombi.Store/Migrations/20180928201334_Votes.cs @@ -0,0 +1,46 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations +{ + public partial class Votes : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Votes", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + RequestId = table.Column(nullable: false), + VoteType = table.Column(nullable: false), + RequestType = table.Column(nullable: false), + UserId = table.Column(nullable: true), + Date = table.Column(nullable: false), + Deleted = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Votes", x => x.Id); + table.ForeignKey( + name: "FK_Votes_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_Votes_UserId", + table: "Votes", + column: "UserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Votes"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index 86694ec23..60927b1ed 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -916,6 +916,30 @@ namespace Ombi.Store.Migrations b.ToTable("UserQualityProfiles"); }); + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Date"); + + b.Property("Deleted"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.Property("VoteType"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => { b.Property("Id") @@ -1128,6 +1152,13 @@ namespace Ombi.Store.Migrations .HasForeignKey("UserId"); }); + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => { b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") diff --git a/src/Ombi/ClientApp/app/app.module.ts b/src/Ombi/ClientApp/app/app.module.ts index d6eb29b53..0f268e4d2 100644 --- a/src/Ombi/ClientApp/app/app.module.ts +++ b/src/Ombi/ClientApp/app/app.module.ts @@ -15,7 +15,7 @@ import { TranslateLoader, TranslateModule } from "@ngx-translate/core"; import { TranslateHttpLoader } from "@ngx-translate/http-loader"; import { CookieService } from "ng2-cookies"; import { GrowlModule } from "primeng/components/growl/growl"; -import { ButtonModule, CaptchaModule, ConfirmationService, ConfirmDialogModule, DataTableModule, DialogModule, SharedModule, SidebarModule, TooltipModule } from "primeng/primeng"; +import { ButtonModule, CaptchaModule, ConfirmationService, ConfirmDialogModule, DataTableModule, DialogModule, OverlayPanelModule, SharedModule, SidebarModule, TooltipModule } from "primeng/primeng"; // Components import { AppComponent } from "./app.component"; @@ -55,6 +55,7 @@ const routes: Routes = [ { loadChildren: "./requests/requests.module#RequestsModule", path: "requests" }, { loadChildren: "./search/search.module#SearchModule", path: "search" }, { loadChildren: "./recentlyAdded/recentlyAdded.module#RecentlyAddedModule", path: "recentlyadded" }, + { loadChildren: "./vote/vote.module#VoteModule", path: "vote" }, ]; // AoT requires an exported function for factories @@ -97,6 +98,7 @@ export function JwtTokenGetter() { CaptchaModule, TooltipModule, ConfirmDialogModule, + OverlayPanelModule, CommonModule, JwtModule.forRoot({ config: { diff --git a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts index f7fe3df87..310aaa6fd 100644 --- a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts @@ -3,6 +3,7 @@ export enum RequestType { movie = 1, tvShow = 2, + } // NEW WORLD diff --git a/src/Ombi/ClientApp/app/interfaces/IVote.ts b/src/Ombi/ClientApp/app/interfaces/IVote.ts new file mode 100644 index 000000000..fb772fea6 --- /dev/null +++ b/src/Ombi/ClientApp/app/interfaces/IVote.ts @@ -0,0 +1,23 @@ +export interface IVoteViewModel { + requestId: number; + requestType: RequestTypes; + image: string; + background: string; + upvotes: number; + downvotes: number; + title: string; + description: string; +} + +export interface IVoteEngineResult { + result: boolean; + message: string; + isError: boolean; + errorMessage: string; +} + +export enum RequestTypes { + TvShow = 0, + Movie = 1, + Album = 2, +} diff --git a/src/Ombi/ClientApp/app/interfaces/index.ts b/src/Ombi/ClientApp/app/interfaces/index.ts index 74a39099e..bfc89edc6 100644 --- a/src/Ombi/ClientApp/app/interfaces/index.ts +++ b/src/Ombi/ClientApp/app/interfaces/index.ts @@ -16,3 +16,4 @@ export * from "./IIssues"; export * from "./IRecentlyAdded"; export * from "./ILidarr"; export * from "./ISearchMusicResult"; +export * from "./IVote"; diff --git a/src/Ombi/ClientApp/app/services/index.ts b/src/Ombi/ClientApp/app/services/index.ts index 59a299d3e..c1ccc2585 100644 --- a/src/Ombi/ClientApp/app/services/index.ts +++ b/src/Ombi/ClientApp/app/services/index.ts @@ -14,3 +14,4 @@ export * from "./issues.service"; export * from "./mobile.service"; export * from "./notificationMessage.service"; export * from "./recentlyAdded.service"; +export * from "./vote.service"; diff --git a/src/Ombi/ClientApp/app/services/vote.service.ts b/src/Ombi/ClientApp/app/services/vote.service.ts new file mode 100644 index 000000000..375f0fc33 --- /dev/null +++ b/src/Ombi/ClientApp/app/services/vote.service.ts @@ -0,0 +1,36 @@ +import { PlatformLocation } from "@angular/common"; +import { HttpClient } from "@angular/common/http"; +import { Injectable } from "@angular/core"; + +import { IVoteEngineResult, IVoteViewModel } from "../interfaces"; +import { ServiceHelpers } from "./service.helpers"; + +@Injectable() +export class VoteService extends ServiceHelpers { + constructor(public http: HttpClient, public platformLocation: PlatformLocation) { + super(http, "/api/v1/Vote/", platformLocation); + } + + public async getModel(): Promise { + return await this.http.get(`${this.url}`, {headers: this.headers}).toPromise(); + } + + public async upvoteMovie(requestId: number): Promise { + return await this.http.post(`${this.url}up/movie/${requestId}`, {headers: this.headers}).toPromise(); + } + public async upvoteTv(requestId: number): Promise { + return await this.http.post(`${this.url}up/tv/${requestId}`, {headers: this.headers}).toPromise(); + } + public async upvoteAlbum(requestId: number): Promise { + return await this.http.post(`${this.url}up/album/${requestId}`, {headers: this.headers}).toPromise(); + } + public async downvoteMovie(requestId: number): Promise { + return await this.http.post(`${this.url}down/movie/${requestId}`, {headers: this.headers}).toPromise(); + } + public async downvoteTv(requestId: number): Promise { + return await this.http.post(`${this.url}down/tv/${requestId}`, {headers: this.headers}).toPromise(); + } + public async downvoteAlbum(requestId: number): Promise { + return await this.http.post(`${this.url}down/album/${requestId}`, {headers: this.headers}).toPromise(); + } +} diff --git a/src/Ombi/ClientApp/app/vote/vote.component.html b/src/Ombi/ClientApp/app/vote/vote.component.html new file mode 100644 index 000000000..eaeb3ca5e --- /dev/null +++ b/src/Ombi/ClientApp/app/vote/vote.component.html @@ -0,0 +1,35 @@ +

Vote

+ +
+ + + + + + + + + + + + + + + + + + +
TitleDescription
+ + + poster{{vm.title}}
+ + +
+ + + poster + \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/vote/vote.component.scss b/src/Ombi/ClientApp/app/vote/vote.component.scss new file mode 100644 index 000000000..a57fb9749 --- /dev/null +++ b/src/Ombi/ClientApp/app/vote/vote.component.scss @@ -0,0 +1,12 @@ +.vcenter { + vertical-align: middle; + float: none; +} + +.hideBackground { + border: 0px solid transparent !important; + background: transparent !important; + -webkit-box-shadow: 0 0px 0px 0 transparent !important; + -moz-box-shadow: 0 0px 0px 0 transparent !important; + box-shadow: 0 0px 0px 0 transparent !important; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/vote/vote.component.ts b/src/Ombi/ClientApp/app/vote/vote.component.ts new file mode 100644 index 000000000..908c1759a --- /dev/null +++ b/src/Ombi/ClientApp/app/vote/vote.component.ts @@ -0,0 +1,70 @@ +import { Component, OnInit, ViewChild } from "@angular/core"; + +import { OverlayPanel } from "primeng/primeng"; +import { NotificationService, VoteService } from "../services"; + +import { IVoteEngineResult, IVoteViewModel, RequestTypes } from "../interfaces"; + +@Component({ + templateUrl: "vote.component.html", + styleUrls: ["vote.component.scss"], +}) +export class VoteComponent implements OnInit { + + public viewModel: IVoteViewModel[]; + public panelImage: string; + @ViewChild("op") public overlayPanel: OverlayPanel; + + constructor(private voteService: VoteService, private notificationSerivce: NotificationService) { } + + public async ngOnInit() { + this.viewModel = await this.voteService.getModel(); + } + + public toggle(event: any, image: string) { + this.panelImage = image; + this.overlayPanel.toggle(event); + } + + public async upvote(vm: IVoteViewModel) { + let result: IVoteEngineResult = {errorMessage:"", isError: false, message:"",result:false}; + switch(vm.requestType) { + case RequestTypes.Album: + result = await this.voteService.upvoteAlbum(vm.requestId); + break; + case RequestTypes.Movie: + result = await this.voteService.upvoteMovie(vm.requestId); + break; + case RequestTypes.TvShow: + result = await this.voteService.upvoteTv(vm.requestId); + break; + } + + if(result.isError) { + this.notificationSerivce.error(result.errorMessage); + } else { + this.notificationSerivce.success("Voted!"); + } + } + + public async downvote(vm: IVoteViewModel) { + let result: IVoteEngineResult = {errorMessage:"", isError: false, message:"",result:false}; + switch(vm.requestType) { + case RequestTypes.Album: + result = await this.voteService.downvoteAlbum(vm.requestId); + break; + case RequestTypes.Movie: + result = await this.voteService.downvoteMovie(vm.requestId); + break; + case RequestTypes.TvShow: + result = await this.voteService.downvoteTv(vm.requestId); + break; + } + + if(result.isError) { + this.notificationSerivce.error(result.errorMessage); + } else { + this.notificationSerivce.success("Voted!"); + } + } +} diff --git a/src/Ombi/ClientApp/app/vote/vote.module.ts b/src/Ombi/ClientApp/app/vote/vote.module.ts new file mode 100644 index 000000000..ee7532da5 --- /dev/null +++ b/src/Ombi/ClientApp/app/vote/vote.module.ts @@ -0,0 +1,41 @@ +import { NgModule } from "@angular/core"; +import { RouterModule, Routes } from "@angular/router"; + +import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; +import { OrderModule } from "ngx-order-pipe"; +import { OverlayPanelModule, SharedModule, TabViewModule } from "primeng/primeng"; + +import { VoteService } from "../services"; + +import { AuthGuard } from "../auth/auth.guard"; + +import { SharedModule as OmbiShared } from "../shared/shared.module"; + +import { VoteComponent } from "./vote.component"; + +const routes: Routes = [ + { path: "", component: VoteComponent, canActivate: [AuthGuard] }, +]; + +@NgModule({ + imports: [ + RouterModule.forChild(routes), + NgbModule.forRoot(), + SharedModule, + OrderModule, + OmbiShared, + TabViewModule, + OverlayPanelModule, + ], + declarations: [ + VoteComponent, + ], + exports: [ + RouterModule, + ], + providers: [ + VoteService, + ], + +}) +export class VoteModule { } diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index a9f3119fa..98f5e3e99 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -1007,5 +1007,4 @@ a > h4:hover { .album-cover { width:300px; -} - +} \ No newline at end of file diff --git a/src/Ombi/Controllers/VoteController.cs b/src/Ombi/Controllers/VoteController.cs index f1466e3ed..70ea0ec8c 100644 --- a/src/Ombi/Controllers/VoteController.cs +++ b/src/Ombi/Controllers/VoteController.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using Microsoft.EntityFrameworkCore; using Ombi.Core.Engine; +using Ombi.Core.Models; using Ombi.Core.Models.UI; using Ombi.Store.Entities; @@ -21,12 +22,69 @@ namespace Ombi.Controllers private readonly IVoteEngine _engine; + /// + /// Returns the viewmodel to render on the UI + /// [HttpGet] public Task> GetView() { return _engine.GetMovieViewModel(); } + /// + /// Upvotes a movie + /// + [HttpPost("up/movie/{requestId:int}")] + public Task UpvoteMovie(int requestId) + { + return _engine.UpVote(requestId, RequestType.Movie); + } + + /// + /// Upvotes a tv show + /// + [HttpPost("up/tv/{requestId:int}")] + public Task UpvoteTv(int requestId) + { + return _engine.UpVote(requestId, RequestType.TvShow); + } + + /// + /// Upvotes a album + /// + [HttpPost("up/album/{requestId:int}")] + public Task UpvoteAlbum(int requestId) + { + return _engine.UpVote(requestId, RequestType.Album); + } + + /// + /// Downvotes a movie + /// + [HttpPost("down/movie/{requestId:int}")] + public Task DownvoteMovie(int requestId) + { + return _engine.DownVote(requestId, RequestType.Movie); + } + + /// + /// Downvotes a tv show + /// + [HttpPost("down/tv/{requestId:int}")] + public Task DownvoteTv(int requestId) + { + return _engine.DownVote(requestId, RequestType.TvShow); + } + + /// + /// Downvotes a album + /// + [HttpPost("down/album/{requestId:int}")] + public Task DownvoteAlbum(int requestId) + { + return _engine.DownVote(requestId, RequestType.Album); + } + /// /// Get's all the votes for the request id /// From 3ab45eb6fdb5c605111b887e7d039372aef5055d Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 28 Sep 2018 23:35:48 +0100 Subject: [PATCH 12/46] Fixed #2549 --- src/Ombi.Core/Senders/MusicSender.cs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs index 9e2dab1bd..60e4ca6ee 100644 --- a/src/Ombi.Core/Senders/MusicSender.cs +++ b/src/Ombi.Core/Senders/MusicSender.cs @@ -79,7 +79,31 @@ namespace Ombi.Core.Senders // Search for it if (!settings.AddOnly) { - await _lidarrApi.AlbumSearch(new[] { result.id }, settings.ApiKey, settings.FullUri); + // get the album + var album = await _lidarrApi.GetAllAlbumsByArtistId(result.id, settings.ApiKey, settings.FullUri); + + var albumToSearch = album.FirstOrDefault(x => + x.foreignAlbumId.Equals(model.ForeignAlbumId, StringComparison.InvariantCultureIgnoreCase)); + var maxRetryCount = 10; // 5 seconds + var currentRetry = 0; + while (albumToSearch != null) + { + if (currentRetry >= maxRetryCount) + { + break; + } + currentRetry++; + await Task.Delay(500); + album = await _lidarrApi.GetAllAlbumsByArtistId(result.id, settings.ApiKey, settings.FullUri); + albumToSearch = album.FirstOrDefault(x => + x.foreignAlbumId.Equals(model.ForeignAlbumId, StringComparison.InvariantCultureIgnoreCase)); + } + + + if (albumToSearch != null) + { + await _lidarrApi.AlbumSearch(new[] {albumToSearch.id}, settings.ApiKey, settings.FullUri); + } } return new SenderResult { Message = "Album has been requested!", Sent = true, Success = true }; } From 85ff2c40175c843e8ae0d49671c0cc87b26b273d Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 2 Oct 2018 20:42:24 +0100 Subject: [PATCH 13/46] Fixed #2555 --- src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts | 1 + .../app/settings/notifications/newsletter.component.html | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts b/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts index fc8b89f1e..f368ee035 100644 --- a/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts @@ -59,6 +59,7 @@ export interface INewsletterNotificationSettings extends INotificationSettings { notificationTemplate: INotificationTemplates; disableMovies: boolean; disableTv: boolean; + disableMusic: boolean; externalEmails: string[]; } diff --git a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.html b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.html index 0a7c27b64..c4d31ae8f 100644 --- a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.html +++ b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.html @@ -20,6 +20,12 @@
+ +
+
+ +
+
From a93fdc66ac56c480d477ccdcfdfe1dd295f912c6 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 3 Oct 2018 13:54:19 +0100 Subject: [PATCH 14/46] Subscribe the user to the request when they vote on it. --- src/Ombi.Core/Engine/VoteEngine.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs index ecd22e848..2cfb1d6b6 100644 --- a/src/Ombi.Core/Engine/VoteEngine.cs +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -85,6 +85,7 @@ namespace Ombi.Core.Engine return new VoteEngineResult { ErrorMessage = "You have already voted!" }; } await RemoveCurrentVote(currentVote); + await _movieRequestEngine.SubscribeToRequest(requestId, requestType); await _voteRepository.Add(new Votes { @@ -148,6 +149,8 @@ namespace Ombi.Core.Engine } await RemoveCurrentVote(currentVote); + await _movieRequestEngine.UnSubscribeRequest(requestId, requestType); + await _voteRepository.Add(new Votes { Date = DateTime.UtcNow, From 64a741a60d0b6e2c3e7d77c70e60fcdb84b9fd59 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 3 Oct 2018 14:55:30 +0100 Subject: [PATCH 15/46] Did the vote settings and frontend !wip --- src/Ombi/ClientApp/app/app.component.html | 6 +++ src/Ombi/ClientApp/app/app.component.ts | 2 + .../ClientApp/app/interfaces/ISettings.ts | 7 +++ .../app/services/settings.service.ts | 13 +++++ .../ClientApp/app/settings/settings.module.ts | 3 ++ .../app/settings/settingsmenu.component.html | 1 + .../app/settings/vote/vote.component.html | 50 +++++++++++++++++++ .../app/settings/vote/vote.component.ts | 44 ++++++++++++++++ src/Ombi/Controllers/SettingsController.cs | 32 +++++++++++- src/Ombi/Startup.cs | 2 - src/Ombi/wwwroot/translations/en.json | 1 + 11 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 src/Ombi/ClientApp/app/settings/vote/vote.component.html create mode 100644 src/Ombi/ClientApp/app/settings/vote/vote.component.ts diff --git a/src/Ombi/ClientApp/app/app.component.html b/src/Ombi/ClientApp/app/app.component.html index 24398f088..953e2a9a2 100644 --- a/src/Ombi/ClientApp/app/app.component.html +++ b/src/Ombi/ClientApp/app/app.component.html @@ -54,6 +54,12 @@ {{ 'NavigationBar.UserManagement' | translate }} + diff --git a/src/Ombi/ClientApp/app/settings/vote/vote.component.html b/src/Ombi/ClientApp/app/settings/vote/vote.component.html new file mode 100644 index 000000000..c5877f3d8 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/vote/vote.component.html @@ -0,0 +1,50 @@ + + + +
+ Vote +
+
+
+
+ + +
+
+ +

Vote limits tell Ombi how many votes the request needs before approval.

+

e.g. If the Movie vote limit is 10, it requires 10 Upvotes from 10 different users before it will be approved.

+
+ + + + The limit needs to be greater than or equal to 1 +
+
+ + + The limit needs to be greater than or equal to 1 +
+
+ + + The limit needs to be greater than or equal to 1 +
+ +
+
+ +
+
+
+ +
+ + + + + +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/vote/vote.component.ts b/src/Ombi/ClientApp/app/settings/vote/vote.component.ts new file mode 100644 index 000000000..d99239b96 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/vote/vote.component.ts @@ -0,0 +1,44 @@ +import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; + +import { NotificationService, SettingsService } from "../../services"; + +@Component({ + templateUrl: "./vote.component.html", +}) +export class VoteComponent implements OnInit { + + public form: FormGroup; + + constructor(private settingsService: SettingsService, + private readonly fb: FormBuilder, + private notificationService: NotificationService) { } + + public ngOnInit() { + this.settingsService.getVoteSettings().subscribe(x => { + this.form = this.fb.group({ + enabled: [x.enabled], + movieVoteMax: [x.movieVoteMax, Validators.min(1)], + musicVoteMax: [x.musicVoteMax, Validators.min(1)], + tvShowVoteMax: [x.tvShowVoteMax, Validators.min(1)], + }); + }); + } + + public onSubmit(form: FormGroup) { + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + + const settings = form.value; + + this.settingsService.saveVoteSettings(settings).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved the Vote settings"); + } else { + this.notificationService.success("There was an error when saving the Vote settings"); + } + }); + } +} diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 9785af553..b523250a6 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -599,12 +599,11 @@ namespace Ombi.Controllers /// - /// Save the Issues settings. + /// Save the Vote settings. /// /// The settings. /// [HttpPost("Issues")] - [AllowAnonymous] public async Task IssueSettings([FromBody]IssueSettings settings) { return await Save(settings); @@ -629,6 +628,35 @@ namespace Ombi.Controllers return issues.Enabled; } + /// + /// Save the Vote settings. + /// + /// The settings. + /// + [HttpPost("vote")] + public async Task VoteSettings([FromBody]VoteSettings settings) + { + return await Save(settings); + } + + /// + /// Gets the Vote Settings. + /// + /// + [HttpGet("vote")] + public async Task VoteSettings() + { + return await Get(); + } + + [AllowAnonymous] + [HttpGet("voteenabled")] + public async Task VoteEnabled() + { + var vote = await Get(); + return vote.Enabled; + } + /// /// Saves the email notification settings. /// diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index ffdd87b53..2d86d4471 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -172,8 +172,6 @@ namespace Ombi { // Generate a API Key settings.ApiKey = Guid.NewGuid().ToString("N"); - var userManager = app.ApplicationServices.GetService(); - userManager.CreateAsync(new OmbiUser {UserName = "API User", UserType = UserType.LocalUser}).Wait(); ombiService.SaveSettings(settings); } diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index cbe2c034e..1fd65e663 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -50,6 +50,7 @@ "Requests": "Requests", "UserManagement": "User Management", "Issues":"Issues", + "Vote":"Vote", "Donate": "Donate!", "DonateLibraryMaintainer": "Donate to Library Maintainer", "DonateTooltip": From 9f696bfc7d3358135d12fdfa903091ccca2dede5 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 3 Oct 2018 15:03:41 +0100 Subject: [PATCH 16/46] Do not show available, approved stuff on the vote page !wip --- src/Ombi.Core/Engine/VoteEngine.cs | 34 +++++++++++++------ .../ClientApp/app/vote/vote.component.html | 4 +-- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs index ced3b8f53..6f399f45b 100644 --- a/src/Ombi.Core/Engine/VoteEngine.cs +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -44,6 +44,10 @@ namespace Ombi.Core.Engine var musicRequestsTask = _musicRequestEngine.GetRequests(); foreach (var r in movieRequests) { + if (r.Available || r.Approved || (r.Denied ?? false)) + { + continue; + } // Make model var votes = GetVotes(r.Id, RequestType.Movie); var upVotes = await votes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); @@ -63,6 +67,10 @@ namespace Ombi.Core.Engine foreach (var r in await musicRequestsTask) { + if (r.Available || r.Approved || (r.Denied ?? false)) + { + continue; + } // Make model var votes = GetVotes(r.Id, RequestType.Album); var upVotes = await votes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); @@ -90,6 +98,10 @@ namespace Ombi.Core.Engine var finalsb = new StringBuilder(); foreach (var childRequests in r.ChildRequests) { + if (childRequests.Available || childRequests.Approved || (childRequests.Denied ?? false)) + { + continue; + } foreach (var epInformation in childRequests.SeasonRequests.OrderBy(x => x.SeasonNumber)) { var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); @@ -97,18 +109,18 @@ namespace Ombi.Core.Engine finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString}"); finalsb.Append("
"); } + vm.Add(new VoteViewModel + { + Upvotes = upVotes, + Downvotes = downVotes, + RequestId = childRequests.Id, + RequestType = RequestType.TvShow, + Title = r.Title, + Image = r.PosterPath, + Background = r.Background, + Description = finalsb.ToString() + }); } - vm.Add(new VoteViewModel - { - Upvotes = upVotes, - Downvotes = downVotes, - RequestId = r.Id, - RequestType = RequestType.TvShow, - Title = r.Title, - Image = r.PosterPath, - Background = r.Background, - Description = finalsb.ToString() - }); } return vm; diff --git a/src/Ombi/ClientApp/app/vote/vote.component.html b/src/Ombi/ClientApp/app/vote/vote.component.html index eaeb3ca5e..4f322352d 100644 --- a/src/Ombi/ClientApp/app/vote/vote.component.html +++ b/src/Ombi/ClientApp/app/vote/vote.component.html @@ -14,8 +14,8 @@ - - + + x.VoteType == VoteType.Upvote).CountAsync(); var downVotes = await votes.Where(x => x.VoteType == VoteType.Downvote).CountAsync(); + var myVote = await votes.FirstOrDefaultAsync(x => x.UserId == user.Id && !x.Deleted); vm.Add(new VoteViewModel { Upvotes = upVotes, @@ -84,24 +90,27 @@ namespace Ombi.Core.Engine Title = r.Title, Image = r.Cover, Background = r.Cover, - Description = r.ArtistName + Description = r.ArtistName, + AlreadyVoted = myVote != null, + MyVote = myVote?.VoteType ?? VoteType.Downvote }); } foreach (var r in await tvRequestsTask) { - // Make model - var votes = GetVotes(r.Id, RequestType.TvShow); - var upVotes = await votes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); - var downVotes = await votes.Where(x => x.VoteType == VoteType.Downvote).CountAsync(); - var finalsb = new StringBuilder(); foreach (var childRequests in r.ChildRequests) { + var finalsb = new StringBuilder(); if (childRequests.Available || childRequests.Approved || (childRequests.Denied ?? false)) { continue; } + var votes = GetVotes(childRequests.Id, RequestType.TvShow); + // Make model + var upVotes = await votes.Where(x => x.VoteType == VoteType.Upvote).CountAsync(); + var downVotes = await votes.Where(x => x.VoteType == VoteType.Downvote).CountAsync(); + var myVote = await votes.FirstOrDefaultAsync(x => x.UserId == user.Id && !x.Deleted); foreach (var epInformation in childRequests.SeasonRequests.OrderBy(x => x.SeasonNumber)) { var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); @@ -118,7 +127,9 @@ namespace Ombi.Core.Engine Title = r.Title, Image = r.PosterPath, Background = r.Background, - Description = finalsb.ToString() + Description = finalsb.ToString(), + AlreadyVoted = myVote != null, + MyVote = myVote?.VoteType ?? VoteType.Downvote }); } } @@ -209,7 +220,7 @@ namespace Ombi.Core.Engine { var user = await GetUser(); var currentVote = await GetVoteForUser(requestId, user.Id); - if (currentVote != null && currentVote.VoteType == VoteType.Upvote) + if (currentVote != null && currentVote.VoteType == VoteType.Downvote) { return new VoteEngineResult { ErrorMessage = "You have already voted!" }; } diff --git a/src/Ombi.Core/Models/UI/VoteViewModel.cs b/src/Ombi.Core/Models/UI/VoteViewModel.cs index 71d6c95a9..f58db3dbc 100644 --- a/src/Ombi.Core/Models/UI/VoteViewModel.cs +++ b/src/Ombi.Core/Models/UI/VoteViewModel.cs @@ -12,5 +12,7 @@ namespace Ombi.Core.Models.UI public int Downvotes { get; set; } public string Title { get; set; } public string Description { get; set; } + public bool AlreadyVoted { get; set; } + public VoteType MyVote { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/IVote.ts b/src/Ombi/ClientApp/app/interfaces/IVote.ts index fb772fea6..e6aaf9607 100644 --- a/src/Ombi/ClientApp/app/interfaces/IVote.ts +++ b/src/Ombi/ClientApp/app/interfaces/IVote.ts @@ -7,6 +7,8 @@ downvotes: number; title: string; description: string; + alreadyVoted: boolean; + myVote: VoteType; } export interface IVoteEngineResult { @@ -21,3 +23,8 @@ export enum RequestTypes { Movie = 1, Album = 2, } + +export enum VoteType { + Upvote = 0, + Downvote = 1, +} diff --git a/src/Ombi/ClientApp/app/vote/vote.component.html b/src/Ombi/ClientApp/app/vote/vote.component.html index 4f322352d..6d8f8a797 100644 --- a/src/Ombi/ClientApp/app/vote/vote.component.html +++ b/src/Ombi/ClientApp/app/vote/vote.component.html @@ -1,35 +1,92 @@

Vote

-
- - - - - - - - - - - - - - - - - - -
TitleDescription
- - - poster{{vm.title}}
+ + + +
+ +
+
+ + + + + + + + + + + + + + + + + +
TitleDescription
+ + + poster{{vm.title}}
+
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
TitleDescription
+ + + poster{{vm.title}}
+
+ +
+ - poster - \ No newline at end of file + poster + \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/vote/vote.component.ts b/src/Ombi/ClientApp/app/vote/vote.component.ts index 908c1759a..ffab837cd 100644 --- a/src/Ombi/ClientApp/app/vote/vote.component.ts +++ b/src/Ombi/ClientApp/app/vote/vote.component.ts @@ -3,7 +3,7 @@ import { Component, OnInit, ViewChild } from "@angular/core"; import { OverlayPanel } from "primeng/primeng"; import { NotificationService, VoteService } from "../services"; -import { IVoteEngineResult, IVoteViewModel, RequestTypes } from "../interfaces"; +import { IVoteEngineResult, IVoteViewModel, RequestTypes, VoteType } from "../interfaces"; @Component({ templateUrl: "vote.component.html", @@ -11,7 +11,12 @@ import { IVoteEngineResult, IVoteViewModel, RequestTypes } from "../interfaces"; }) export class VoteComponent implements OnInit { + public showCurrent: boolean = true; + public showCompleted: boolean; public viewModel: IVoteViewModel[]; + public currentVotes: IVoteViewModel[]; + public completedVotes: IVoteViewModel[]; + public VoteType = VoteType; public panelImage: string; @ViewChild("op") public overlayPanel: OverlayPanel; @@ -19,8 +24,19 @@ export class VoteComponent implements OnInit { public async ngOnInit() { this.viewModel = await this.voteService.getModel(); + this.filterLists(); } + public selectCurrentTab() { + this.showCurrent = true; + this.showCompleted = false; + } + + public selectCompletedVotesTab() { + this.showCurrent = false; + this.showCompleted = true; + } + public toggle(event: any, image: string) { this.panelImage = image; this.overlayPanel.toggle(event); @@ -44,6 +60,9 @@ export class VoteComponent implements OnInit { this.notificationSerivce.error(result.errorMessage); } else { this.notificationSerivce.success("Voted!"); + vm.alreadyVoted = true; + vm.myVote = VoteType.Upvote; + this.filterLists(); } } @@ -64,7 +83,19 @@ export class VoteComponent implements OnInit { if(result.isError) { this.notificationSerivce.error(result.errorMessage); } else { - this.notificationSerivce.success("Voted!"); + this.notificationSerivce.success("Voted!"); + vm.alreadyVoted = true; + vm.myVote = VoteType.Downvote; + this.filterLists(); } } + + private filterLists() { + this.completedVotes = this.viewModel.filter(vm => { + return vm.alreadyVoted; + }); + this.currentVotes = this.viewModel.filter(vm => { + return !vm.alreadyVoted; + }); + } } diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index 1fd65e663..93f6c39f0 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -194,5 +194,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } From a7cd9c565d1cf365a0f58c6c47d883954f8c949e Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:53:56 +0100 Subject: [PATCH 18/46] New translations en.json (Danish) --- src/Ombi/wwwroot/translations/da.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index 17c671217..0229b3603 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -48,6 +48,7 @@ "Requests": "Anmodninger", "UserManagement": "Brugeradministration", "Issues": "Problemer", + "Vote": "Vote", "Donate": "Donér!", "DonateLibraryMaintainer": "Donér til vedligeholder af bibliotek", "DonateTooltip": "Sådan overbeviser jeg min kone om, at jeg skal bruge min fritid på at udvikle Ombi :)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 10e6145ff074f7e070143195a2ca3cd74755a374 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:53:57 +0100 Subject: [PATCH 19/46] New translations en.json (Dutch) --- src/Ombi/wwwroot/translations/nl.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 60d54fe8c..18a1d319d 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -48,6 +48,7 @@ "Requests": "Verzoeklijst", "UserManagement": "Gebruikersbeheer", "Issues": "Problemen", + "Vote": "Vote", "Donate": "Doneer!", "DonateLibraryMaintainer": "Doneren aan bibliotheek beheerder", "DonateTooltip": "Zo heb ik mijn vrouw overtuigd dat ik Ombi mag ontwikkelen ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From ad78a3947170b9f51155ae15252903338fce8905 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:53:58 +0100 Subject: [PATCH 20/46] New translations en.json (French) --- src/Ombi/wwwroot/translations/fr.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 0834653f8..c20dffdb0 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -48,6 +48,7 @@ "Requests": "Demandes", "UserManagement": "Gestion des utilisateurs", "Issues": "Problèmes", + "Vote": "Vote", "Donate": "Faire un don !", "DonateLibraryMaintainer": "Faire un don au mainteneur de la bibliothèque", "DonateTooltip": "C’est pour convaincre ma femme de me laisser passer mon temps libre à développer Ombi ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 7218aeff775271d426fa1d37b54e5f43a0f38701 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:00 +0100 Subject: [PATCH 21/46] New translations en.json (German) --- src/Ombi/wwwroot/translations/de.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 2da1aab4e..d5b9e62be 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -48,6 +48,7 @@ "Requests": "Anfragen", "UserManagement": "Benutzerverwaltung", "Issues": "Probleme", + "Vote": "Vote", "Donate": "Spenden!", "DonateLibraryMaintainer": "Spende sie an den Bibliotheks Betreuer", "DonateTooltip": "So überzeuge ich meine Frau, meine Freizeit mit der Entwicklung von Ombi zu verbringen ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 1b097b9147ec8a53d502dc4253987071c17233aa Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:02 +0100 Subject: [PATCH 22/46] New translations en.json (Italian) --- src/Ombi/wwwroot/translations/it.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 25f706303..0ade93919 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -48,6 +48,7 @@ "Requests": "Richieste", "UserManagement": "Gestione degli utenti", "Issues": "Problemi", + "Vote": "Vote", "Donate": "Fai una donazione!", "DonateLibraryMaintainer": "Dona al manutentore della libreria", "DonateTooltip": "Questo è come convinco mia moglie a farmi spendere il mio tempo libero nello sviluppo di Ombi ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 35a28ef62ea843e7037050d4e268897fc5aafbf9 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:03 +0100 Subject: [PATCH 23/46] New translations en.json (Norwegian) --- src/Ombi/wwwroot/translations/no.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 87df0181f..80cd9e31a 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -48,6 +48,7 @@ "Requests": "Forespørsler", "UserManagement": "Brukeradministrasjon", "Issues": "Mangler", + "Vote": "Vote", "Donate": "Doner!", "DonateLibraryMaintainer": "Doner til vedlikeholderen av biblioteket", "DonateTooltip": "Dette er hvordan jeg overbevise min kone til å la meg bruke min fritid til å utvikle Ombi ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 7f4c251104dce16615ce43c3cf57a5f43cbc968a Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:05 +0100 Subject: [PATCH 24/46] New translations en.json (Polish) --- src/Ombi/wwwroot/translations/pl.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index 8e180e5bb..3aba4da41 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -48,6 +48,7 @@ "Requests": "Zgłoszenia", "UserManagement": "Zarządzanie użytkownikami", "Issues": "Problemy", + "Vote": "Vote", "Donate": "Wesprzyj!", "DonateLibraryMaintainer": "Wesprzyj właściciela biblioteki", "DonateTooltip": "W ten sposób przekonuję moją żonę by spędzać mój wolny czas rozwijając Ombi ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 9ec631ca14aaf629e70a525e217b1ceca185a5ee Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:07 +0100 Subject: [PATCH 25/46] New translations en.json (Portuguese, Brazilian) --- src/Ombi/wwwroot/translations/pt.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index e547d0066..eaf45cac9 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -48,6 +48,7 @@ "Requests": "Solicitações", "UserManagement": "Gerenciador de Usuário", "Issues": "Problemas", + "Vote": "Vote", "Donate": "Fazer uma doação!", "DonateLibraryMaintainer": "Doar para o Dono da Biblioteca", "DonateTooltip": "É assim que eu convenço a minha mulher a deixar-me passar o meu tempo livre desenvolvendo Ombi;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 6f220940a93c66a61006d4fd9f9490995428ecd7 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:08 +0100 Subject: [PATCH 26/46] New translations en.json (Spanish) --- src/Ombi/wwwroot/translations/es.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index a49ea5140..dc7637e79 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -48,6 +48,7 @@ "Requests": "Solicitudes", "UserManagement": "Gestión de usuarios", "Issues": "Incidencias", + "Vote": "Vote", "Donate": "¡Donar!", "DonateLibraryMaintainer": "Donate to Library Maintainer", "DonateTooltip": "Para que mi esposa me deje desarrollar Ombi ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From bd4f423220d0ae24eda95c74af92165cf7088442 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 13:54:09 +0100 Subject: [PATCH 27/46] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 26a85fe10..8d2e8374a 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -48,6 +48,7 @@ "Requests": "Förfrågningar", "UserManagement": "Användarhantering", "Issues": "Problem", + "Vote": "Vote", "Donate": "Donera!", "DonateLibraryMaintainer": "Donera till bibliotekets utvecklare", "DonateTooltip": "Det är så här jag övertygar min fru att jag vill spendera min fritid att utveckla Ombi ;)", @@ -188,5 +189,9 @@ "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" } } \ No newline at end of file From 9d8caf43584c4e896f65e2d9cbc9dc0072c977a3 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 4 Oct 2018 14:31:40 +0100 Subject: [PATCH 28/46] New translations en.json (German) --- src/Ombi/wwwroot/translations/de.json | 38 +++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index d5b9e62be..c3646221d 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -48,7 +48,7 @@ "Requests": "Anfragen", "UserManagement": "Benutzerverwaltung", "Issues": "Probleme", - "Vote": "Vote", + "Vote": "Bewerten", "Donate": "Spenden!", "DonateLibraryMaintainer": "Spende sie an den Bibliotheks Betreuer", "DonateTooltip": "So überzeuge ich meine Frau, meine Freizeit mit der Entwicklung von Ombi zu verbringen ;)", @@ -66,27 +66,27 @@ "Danish": "Dänisch", "Dutch": "Niederländisch", "Norwegian": "Norwegisch", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" + "BrazillianPortuguese": "Portugiesisch (Brasilien)", + "Polish": "Polnisch", + "Swedish": "Schwedisch" }, "OpenMobileApp": "Mobile App", - "RecentlyAdded": "Recently Added" + "RecentlyAdded": "Kürzlich hinzugefügt" }, "Search": { "Title": "Suche", "Paragraph": "Möchtest du etwas sehen, das nicht verfügbar ist? Kein Problem, benutze einfach die Suchbox und fordere es an!", "MoviesTab": "Filme", "TvTab": "Serien", - "MusicTab": "Music", + "MusicTab": "Musik", "Suggestions": "Vorschläge", "NoResults": "Es tut uns leid, wir haben keine Ergebnisse gefunden!", "DigitalDate": "Digital Release: {{date}}", - "TheatricalRelease": "Theatrical Release: {{date}}", + "TheatricalRelease": "Kinostart: {{date}}", "ViewOnPlex": "In Plex anschauen", "ViewOnEmby": "In Emby anschauen", "RequestAdded": "Anfrage für {{title}} wurde erfolgreich hinzugefügt", - "Similar": "Similar", + "Similar": "Ähnliche", "Movies": { "PopularMovies": "Beliebte Filme", "UpcomingMovies": "Kommende Filme", @@ -116,14 +116,14 @@ "Paragraph": "Unten sehen Sie Ihre und alle anderen Anfragen, sowie deren Download und Genehmigungsstatus.", "MoviesTab": "Filme", "TvTab": "Serien", - "MusicTab": "Music", + "MusicTab": "Musik", "RequestedBy": "Angefordert von:", "Status": "Status:", "RequestStatus": "Anfrage Status:", "Denied": " Abgelehnt:", - "TheatricalRelease": "Theatrical Release: {{date}}", + "TheatricalRelease": "Kinostart: {{date}}", "ReleaseDate": "Veröffentlicht: {{date}}", - "TheatricalReleaseSort": "Theatrical Release", + "TheatricalReleaseSort": "Kinostart", "DigitalRelease": "Digital Release: {{date}}", "RequestDate": "Datum der Anfrage:", "QualityOverride": "Qualitäts Überschreiben:", @@ -140,10 +140,10 @@ "GridStatus": "Status", "ReportIssue": "Problem melden", "Filter": "Filter", - "Sort": "Sort", + "Sort": "Sortieren", "SeasonNumberHeading": "Staffel: {seasonNumber}", - "SortTitleAsc": "Title ▲", - "SortTitleDesc": "Title ▼", + "SortTitleAsc": "Titel ▲", + "SortTitleDesc": "Titel ▼", "SortRequestDateAsc": "Request Date ▲", "SortRequestDateDesc": "Request Date ▼", "SortStatusAsc": "Status ▲", @@ -180,18 +180,18 @@ "FilterHeaderAvailability": "Verfügbarkeit", "FilterHeaderRequestStatus": "Status", "Approved": "Bestätigt", - "PendingApproval": "Pending Approval" + "PendingApproval": "Genehmigung ausstehend" }, "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} remaining", "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" + "MovieDue": "Film: {{date}}", + "MusicDue": "Musik: {{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" + "CompletedVotesTab": "Bewertet", + "VotesTab": "Erforderliche Bewertungen" } } \ No newline at end of file From e8fbf53755b318841e54a58686c471d4c86f5566 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Fri, 5 Oct 2018 13:04:47 +0100 Subject: [PATCH 29/46] Date and times are now in the local users date time --- .../app/issues/issueDetails.component.html | 2 +- .../app/requests/movierequests.component.html | 8 ++++---- .../requests/music/musicrequests.component.html | 4 ++-- .../requests/tvrequest-children.component.html | 2 +- .../app/requests/tvrequests.component.html | 4 ++-- .../app/search/moviesearch.component.html | 6 +++--- .../app/search/moviesearchgrid.component.html | 4 ++-- .../app/search/music/albumsearch.component.html | 2 +- .../app/search/seriesinformation.component.html | 2 +- .../ClientApp/app/search/tvsearch.component.html | 4 ++-- src/Ombi/ClientApp/app/shared/shared.module.ts | 3 +++ .../usermanagement/usermanagement.component.html | 15 +++++++++++---- 12 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/Ombi/ClientApp/app/issues/issueDetails.component.html b/src/Ombi/ClientApp/app/issues/issueDetails.component.html index 33157cd09..44be113c6 100644 --- a/src/Ombi/ClientApp/app/issues/issueDetails.component.html +++ b/src/Ombi/ClientApp/app/issues/issueDetails.component.html @@ -63,7 +63,7 @@

{{comment.comment}}

- +
diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index a35ede06c..6167fbac0 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -58,7 +58,7 @@ -
{{ 'Requests.TheatricalRelease' | translate: {date: request.releaseDate | date: 'mediumDate'} }}
-
{{ 'Requests.DigitalRelease' | translate: {date: request.digitalReleaseDate | date: 'mediumDate'} }}
-
{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | date}}
+
{{ 'Requests.TheatricalRelease' | translate: {date: request.releaseDate | amLocal | amDateFormat: 'LL'} }}
+
{{ 'Requests.DigitalRelease' | translate: {date: request.digitalReleaseDate | amLocal | amDateFormat: 'LL'} }}
+
{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | amLocal | amDateFormat: 'LL'}}

diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html index f6ad4bb2a..caa1ca2d6 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html @@ -97,8 +97,8 @@
-
{{ 'Requests.ReleaseDate' | translate: {date: request.releaseDate | date: 'mediumDate'} }}
-
{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | date: 'mediumDate'}}
+
{{ 'Requests.ReleaseDate' | translate: {date: request.releaseDate | amLocal | amDateFormat: 'LL'} }}
+
{{ 'Requests.RequestDate' | translate }} {{request.requestedDate | amLocal | amDateFormat: 'LL'}}

+ + {{u.lastLoggedIn | amLocal | amDateFormat: 'l LT'}} + + + Not logged in yet! + + Local User From 293aa8823457c6acd79c07aca659fa647a73699d Mon Sep 17 00:00:00 2001 From: Victor Usoltsev Date: Sat, 6 Oct 2018 23:09:02 +1300 Subject: [PATCH 30/46] Hides Sonarr options on tv requests page if only 1 option available. --- src/Ombi/ClientApp/app/requests/tvrequests.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.html b/src/Ombi/ClientApp/app/requests/tvrequests.component.html index e4d10d72e..801998c71 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.html @@ -50,7 +50,7 @@ View
-
+
@@ -66,7 +66,7 @@
-
+
From f8cda54002a33f5e37a3a902b14b4e25f4aa8bd5 Mon Sep 17 00:00:00 2001 From: Victor Usoltsev Date: Sat, 6 Oct 2018 23:30:32 +1300 Subject: [PATCH 31/46] Hides Radarr options on movie requests page if only 1 option available. --- src/Ombi/ClientApp/app/requests/movierequests.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index 6167fbac0..05d0ca14f 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -129,7 +129,7 @@ -
+
@@ -145,7 +145,7 @@
-
+
From 42eb5ca9117bc801575fddafea0f4028d560648b Mon Sep 17 00:00:00 2001 From: Victor Usoltsev Date: Sun, 7 Oct 2018 02:06:30 +1300 Subject: [PATCH 32/46] Changes language selector to always show native language name. --- src/Ombi/ClientApp/app/app.component.html | 22 +++++++++++----------- src/Ombi/wwwroot/translations/da.json | 13 ------------- src/Ombi/wwwroot/translations/de.json | 13 ------------- src/Ombi/wwwroot/translations/en.json | 13 ------------- src/Ombi/wwwroot/translations/es.json | 13 ------------- src/Ombi/wwwroot/translations/fr.json | 13 ------------- src/Ombi/wwwroot/translations/it.json | 13 ------------- src/Ombi/wwwroot/translations/nl.json | 13 ------------- src/Ombi/wwwroot/translations/no.json | 13 ------------- src/Ombi/wwwroot/translations/pl.json | 13 ------------- src/Ombi/wwwroot/translations/pt.json | 13 ------------- src/Ombi/wwwroot/translations/sv.json | 13 ------------- 12 files changed, 11 insertions(+), 154 deletions(-) diff --git a/src/Ombi/ClientApp/app/app.component.html b/src/Ombi/ClientApp/app/app.component.html index 953e2a9a2..d695ac61c 100644 --- a/src/Ombi/ClientApp/app/app.component.html +++ b/src/Ombi/ClientApp/app/app.component.html @@ -117,37 +117,37 @@ diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index 0229b3603..7786d69ad 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -57,19 +57,6 @@ "Welcome": "Velkommen til {{username}}", "UpdateDetails": "Opdater loginoplysninger", "Logout": "Log af", - "Language": { - "English": "Engelsk", - "French": "Fransk", - "Spanish": "Spansk", - "German": "Tysk", - "Italian": "Italiensk", - "Danish": "Dansk", - "Dutch": "Hollandsk", - "Norwegian": "Norsk", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Åbn mobilapp", "RecentlyAdded": "Recently Added" }, diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index c3646221d..2dccedb1f 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -57,19 +57,6 @@ "Welcome": "Willkommen {{username}}", "UpdateDetails": "Update-Details", "Logout": "Ausloggen", - "Language": { - "English": "Englisch", - "French": "Französisch", - "Spanish": "Spanisch", - "German": "Deutsch", - "Italian": "Italienisch", - "Danish": "Dänisch", - "Dutch": "Niederländisch", - "Norwegian": "Norwegisch", - "BrazillianPortuguese": "Portugiesisch (Brasilien)", - "Polish": "Polnisch", - "Swedish": "Schwedisch" - }, "OpenMobileApp": "Mobile App", "RecentlyAdded": "Kürzlich hinzugefügt" }, diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index 93f6c39f0..2d6d81e94 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -60,19 +60,6 @@ "Welcome": "Welcome {{username}}", "UpdateDetails": "Update Details", "Logout": "Logout", - "Language": { - "English": "English", - "French": "French", - "Spanish": "Spanish", - "German": "German", - "Italian": "Italian", - "Danish": "Danish", - "Dutch": "Dutch", - "Norwegian":"Norwegian", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish":"Polish", - "Swedish":"Swedish" - }, "OpenMobileApp":"Open Mobile App", "RecentlyAdded":"Recently Added" }, diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index dc7637e79..a9f8c2b5e 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -57,19 +57,6 @@ "Welcome": "Bienvenido {{username}}", "UpdateDetails": "Detalles de la actualización", "Logout": "Cerrar sesión", - "Language": { - "English": "Inglés", - "French": "Francés", - "Spanish": "Español", - "German": "Alemán", - "Italian": "Italiano", - "Danish": "Danés", - "Dutch": "Holandés", - "Norwegian": "Norwegian", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Open Mobile App", "RecentlyAdded": "Recently Added" }, diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index c20dffdb0..bf6e26a93 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -57,19 +57,6 @@ "Welcome": "Bienvenue {{username}}", "UpdateDetails": "Détails de la mise à jour", "Logout": "Déconnexion", - "Language": { - "English": "Anglais", - "French": "Français", - "Spanish": "Espagnol", - "German": "Allemand", - "Italian": "Italien", - "Danish": "Danois", - "Dutch": "Néerlandais", - "Norwegian": "Norvégien", - "BrazillianPortuguese": "Portuguais brésilien", - "Polish": "Polonais", - "Swedish": "Swedish" - }, "OpenMobileApp": "Ouvrir l'application mobile", "RecentlyAdded": "Ajouts récents" }, diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 0ade93919..bfa026be0 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -57,19 +57,6 @@ "Welcome": "Benvenuto {{username}}", "UpdateDetails": "Aggiorna i tuoi dati", "Logout": "Logout", - "Language": { - "English": "Inglese", - "French": "Francese", - "Spanish": "Spagnolo", - "German": "Tedesco", - "Italian": "Italiano", - "Danish": "Danese", - "Dutch": "Olandese", - "Norwegian": "Norvegese", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Apri l'applicazione mobile", "RecentlyAdded": "Recently Added" }, diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 18a1d319d..24ce67966 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -57,19 +57,6 @@ "Welcome": "Welkom {{username}}", "UpdateDetails": "Update gegevens", "Logout": "Logout", - "Language": { - "English": "Engels", - "French": "Frans", - "Spanish": "Spaans", - "German": "Duits", - "Italian": "Italiaans", - "Danish": "Deens", - "Dutch": "Nederlands", - "Norwegian": "Noors", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Open Mobiele App", "RecentlyAdded": "Recently Added" }, diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 80cd9e31a..6f84943a8 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -57,19 +57,6 @@ "Welcome": "Velkommen {{username}}", "UpdateDetails": "Oppdater detaljer", "Logout": "Logg av", - "Language": { - "English": "Engelsk", - "French": "Fransk", - "Spanish": "Spansk", - "German": "Tysk", - "Italian": "Italiensk", - "Danish": "Dansk", - "Dutch": "Nederlandsk", - "Norwegian": "Norsk", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" - }, "OpenMobileApp": "Åpne mobilapp", "RecentlyAdded": "Recently Added" }, diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index 3aba4da41..b53f7f1c1 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -57,19 +57,6 @@ "Welcome": "Witaj {{username}}", "UpdateDetails": "Podaj szczegóły", "Logout": "Wyloguj", - "Language": { - "English": "Angielski", - "French": "Francuski", - "Spanish": "Hiszpański", - "German": "Niemiecki", - "Italian": "Włoski", - "Danish": "Duński", - "Dutch": "Holenderski", - "Norwegian": "Norweski", - "BrazillianPortuguese": "Brazylijski portugalski", - "Polish": "Polski", - "Swedish": "Swedish" - }, "OpenMobileApp": "Otwórz aplikację mobilną", "RecentlyAdded": "Ostatnio dodane" }, diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index eaf45cac9..199f06593 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -57,19 +57,6 @@ "Welcome": "Bem-vindo, {{username}}", "UpdateDetails": "Detalhes da Atualização", "Logout": "Sair", - "Language": { - "English": "Inglês", - "French": "Francês", - "Spanish": "Espanhol", - "German": "Alemão", - "Italian": "Italiano", - "Danish": "Dinamarquês", - "Dutch": "Holandês", - "Norwegian": "Norueguês", - "BrazillianPortuguese": "Português (Brasil)", - "Polish": "Polonês", - "Swedish": "Swedish" - }, "OpenMobileApp": "Abrir aplicativo do celular", "RecentlyAdded": "Recentemente adicionado" }, diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 8d2e8374a..6da35d413 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -57,19 +57,6 @@ "Welcome": "Välkommen {{username}}", "UpdateDetails": "Uppdatera information", "Logout": "Logga ut", - "Language": { - "English": "Engelska", - "French": "Franska", - "Spanish": "Spanska", - "German": "Tyska", - "Italian": "Italienska", - "Danish": "Danska", - "Dutch": "Holländska", - "Norwegian": "Norska", - "BrazillianPortuguese": "Brazillian portugisiska", - "Polish": "Polska", - "Swedish": "Swedish" - }, "OpenMobileApp": "Öppna Mobil App", "RecentlyAdded": "Nyligen tillagda" }, From dcab7773be13fcb78b168666d76087ec3840ed44 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 20:51:30 +0100 Subject: [PATCH 33/46] New translations en.json (Danish) --- src/Ombi/wwwroot/translations/da.json | 70 +++++++++++++-------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index 0229b3603..b60fb6c7e 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -12,8 +12,8 @@ "Common": { "ContinueButton": "Fortsæt", "Available": "Tilgængelig", - "PartiallyAvailable": "Partially Available", - "Monitored": "Monitored", + "PartiallyAvailable": "Delvist tilgængelig", + "Monitored": "Overvåget", "NotAvailable": "Ikke tilgængelig", "ProcessingRequest": "Behandler anmodning", "PendingApproval": "Afventer godkendelse", @@ -48,7 +48,7 @@ "Requests": "Anmodninger", "UserManagement": "Brugeradministration", "Issues": "Problemer", - "Vote": "Vote", + "Vote": "Stem", "Donate": "Donér!", "DonateLibraryMaintainer": "Donér til vedligeholder af bibliotek", "DonateTooltip": "Sådan overbeviser jeg min kone om, at jeg skal bruge min fritid på at udvikle Ombi :)", @@ -66,27 +66,27 @@ "Danish": "Dansk", "Dutch": "Hollandsk", "Norwegian": "Norsk", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish", - "Swedish": "Swedish" + "BrazillianPortuguese": "Brasiliansk portugisisk", + "Polish": "Polsk", + "Swedish": "Svensk" }, "OpenMobileApp": "Åbn mobilapp", - "RecentlyAdded": "Recently Added" + "RecentlyAdded": "Senest tilføjet" }, "Search": { "Title": "Søg", "Paragraph": "Ønsker du at se noget, som er utilgængeligt? intet problem, bare søg efter det nedenfor og anmod om det!", "MoviesTab": "Film", "TvTab": "Tv-serier", - "MusicTab": "Music", + "MusicTab": "Musik", "Suggestions": "Forslag", "NoResults": "Beklager, vi fandt ingen resultater!", - "DigitalDate": "Digital Release: {{date}}", - "TheatricalRelease": "Theatrical Release: {{date}}", + "DigitalDate": "Digital udgivelse: {{date}}", + "TheatricalRelease": "Biografudgivelse: {{date}}", "ViewOnPlex": "Se på Plex", "ViewOnEmby": "Se på Emby", "RequestAdded": "{{title}} er anmodet med succes", - "Similar": "Similar", + "Similar": "Lignende", "Movies": { "PopularMovies": "Populære film", "UpcomingMovies": "Kommende film", @@ -116,15 +116,15 @@ "Paragraph": "Herunder kan du se dine og alle andre anmodninger, samt status for download og godkendelse.", "MoviesTab": "Film", "TvTab": "Tv-serier", - "MusicTab": "Music", + "MusicTab": "Musik", "RequestedBy": "Anmodet af:", "Status": "Status:", "RequestStatus": "Status for anmodning:", "Denied": " Afvist:", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ReleaseDate": "Released: {{date}}", - "TheatricalReleaseSort": "Theatrical Release", - "DigitalRelease": "Digital Release: {{date}}", + "TheatricalRelease": "Biografudgivelse: {{date}}", + "ReleaseDate": "Udgivet: {{date}}", + "TheatricalReleaseSort": "Biografudgivelse", + "DigitalRelease": "Digital udgivelse: {{date}}", "RequestDate": "Dato for anmodning:", "QualityOverride": "Tilsidesæt kvalitet:", "RootFolderOverride": "Tilsidesæt rodmappe:", @@ -140,20 +140,20 @@ "GridStatus": "Status", "ReportIssue": "Rapportér problem", "Filter": "Filter", - "Sort": "Sort", + "Sort": "Sorter", "SeasonNumberHeading": "Sæson: {seasonNumber}", - "SortTitleAsc": "Title ▲", - "SortTitleDesc": "Title ▼", - "SortRequestDateAsc": "Request Date ▲", - "SortRequestDateDesc": "Request Date ▼", + "SortTitleAsc": "Titel ▲", + "SortTitleDesc": "Titel ▼", + "SortRequestDateAsc": "Dato for anmodning ▲", + "SortRequestDateDesc": "Dato for anmodning ▼", "SortStatusAsc": "Status ▲", "SortStatusDesc": "Status ▼", "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", - "NextDays": "Another request will be added in {{time}} days", - "NextHours": "Another request will be added in {{time}} hours", - "NextMinutes": "Another request will be added in {{time}} minutes", - "NextMinute": "Another request will be added in {{time}} minute" + "Quota": "{{remaining}}/{{total}} anmodninger, der er tilbage", + "NextDays": "En anden anmodning vil blive tilføjet i {{time}} Dage", + "NextHours": "En anden anmodning vil blive tilføjet i {{time}} Timer", + "NextMinutes": "En anden anmodning vil blive tilføjet i {{time}} Minutter", + "NextMinute": "En anden anmodning vil blive tilføjet i {{time}} Minut" } }, "Issues": { @@ -180,18 +180,18 @@ "FilterHeaderAvailability": "Tilgængelighed", "FilterHeaderRequestStatus": "Status", "Approved": "Godkendt", - "PendingApproval": "Pending Approval" + "PendingApproval": "Afventer godkendelse" }, "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", - "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" + "TvRemaining": "Tv: {{remaining}}/{{total}} Resterende", + "MovieRemaining": "Film: {{remaining}}/{{total}} Resterende", + "MusicRemaining": "Musik: {{remaining}}/{{total}} Resterende", + "TvDue": "Tv: {{date}}", + "MovieDue": "Film: {{date}}", + "MusicDue": "Musik: {{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" + "CompletedVotesTab": "Stemt", + "VotesTab": "Nødvendige stemmer" } } \ No newline at end of file From 12d37511eef4c7c30e4d6358cad7ee116c2e67d7 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 20:55:38 +0100 Subject: [PATCH 34/46] Potentially fix the user profiles issue --- .../Controllers/External/RadarrController.cs | 34 ++++++++----------- .../Controllers/External/SonarrController.cs | 1 + 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/Ombi/Controllers/External/RadarrController.cs b/src/Ombi/Controllers/External/RadarrController.cs index 128b1a9e2..882f55283 100644 --- a/src/Ombi/Controllers/External/RadarrController.cs +++ b/src/Ombi/Controllers/External/RadarrController.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Caching.Memory; using Ombi.Api.Radarr; using Ombi.Api.Radarr.Models; using Ombi.Attributes; @@ -13,9 +12,9 @@ using Ombi.Settings.Settings.Models.External; namespace Ombi.Controllers.External { - [Authorize] - [ApiV1] - [Produces("application/json")] + [Authorize] + [ApiV1] + [Produces("application/json")] public class RadarrController : Controller { public RadarrController(IRadarrApi radarr, ISettingsService settings, @@ -24,6 +23,7 @@ namespace Ombi.Controllers.External RadarrApi = radarr; RadarrSettings = settings; Cache = mem; + RadarrSettings.ClearCache(); } private IRadarrApi RadarrApi { get; } @@ -61,15 +61,12 @@ namespace Ombi.Controllers.External [HttpGet("Profiles")] public async Task> GetProfiles() { - return await Cache.GetOrAdd(CacheKeys.RadarrQualityProfiles, async () => + var settings = await RadarrSettings.GetSettingsAsync(); + if (settings.Enabled) { - var settings = await RadarrSettings.GetSettingsAsync(); - if (settings.Enabled) - { - return await RadarrApi.GetProfiles(settings.ApiKey, settings.FullUri); - } - return null; - }, DateTime.Now.AddHours(1)); + return await RadarrApi.GetProfiles(settings.ApiKey, settings.FullUri); + } + return null; } /// @@ -80,15 +77,12 @@ namespace Ombi.Controllers.External [HttpGet("RootFolders")] public async Task> GetRootFolders() { - return await Cache.GetOrAdd(CacheKeys.RadarrRootProfiles, async () => + var settings = await RadarrSettings.GetSettingsAsync(); + if (settings.Enabled) { - var settings = await RadarrSettings.GetSettingsAsync(); - if (settings.Enabled) - { - return await RadarrApi.GetRootFolders(settings.ApiKey, settings.FullUri); - } - return null; - }, DateTime.Now.AddHours(1)); + return await RadarrApi.GetRootFolders(settings.ApiKey, settings.FullUri); + } + return null; } } } \ No newline at end of file diff --git a/src/Ombi/Controllers/External/SonarrController.cs b/src/Ombi/Controllers/External/SonarrController.cs index 94d1e3edf..a1e90e96f 100644 --- a/src/Ombi/Controllers/External/SonarrController.cs +++ b/src/Ombi/Controllers/External/SonarrController.cs @@ -20,6 +20,7 @@ namespace Ombi.Controllers.External { SonarrApi = sonarr; SonarrSettings = settings; + SonarrSettings.ClearCache(); } private ISonarrApi SonarrApi { get; } From 8bb3b1888d2b8a6f98f0f6e797c33b18267c50db Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 20:57:03 +0100 Subject: [PATCH 35/46] !wip poweruser --- src/Ombi/Controllers/External/RadarrController.cs | 2 ++ src/Ombi/Controllers/External/SonarrController.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Ombi/Controllers/External/RadarrController.cs b/src/Ombi/Controllers/External/RadarrController.cs index 882f55283..623322704 100644 --- a/src/Ombi/Controllers/External/RadarrController.cs +++ b/src/Ombi/Controllers/External/RadarrController.cs @@ -59,6 +59,7 @@ namespace Ombi.Controllers.External /// /// [HttpGet("Profiles")] + [PowerUser] public async Task> GetProfiles() { var settings = await RadarrSettings.GetSettingsAsync(); @@ -75,6 +76,7 @@ namespace Ombi.Controllers.External /// /// [HttpGet("RootFolders")] + [PowerUser] public async Task> GetRootFolders() { var settings = await RadarrSettings.GetSettingsAsync(); diff --git a/src/Ombi/Controllers/External/SonarrController.cs b/src/Ombi/Controllers/External/SonarrController.cs index a1e90e96f..c3401736d 100644 --- a/src/Ombi/Controllers/External/SonarrController.cs +++ b/src/Ombi/Controllers/External/SonarrController.cs @@ -55,6 +55,7 @@ namespace Ombi.Controllers.External /// /// [HttpGet("Profiles")] + [PowerUser] public async Task> GetProfiles() { var settings = await SonarrSettings.GetSettingsAsync(); @@ -70,6 +71,7 @@ namespace Ombi.Controllers.External /// /// [HttpGet("RootFolders")] + [PowerUser] public async Task> GetRootFolders() { var settings = await SonarrSettings.GetSettingsAsync(); From 7763ecca4f844cffc7bd840754c22570cf6b059c Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 7 Oct 2018 21:01:24 +0100 Subject: [PATCH 36/46] Fixed lidarr newsletter bug --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 9f5e58482..88125b7c6 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -98,7 +98,7 @@ namespace Ombi.Schedule.Jobs.Ombi // Get the Content var plexContent = _plex.GetAll().Include(x => x.Episodes).AsNoTracking(); var embyContent = _emby.GetAll().Include(x => x.Episodes).AsNoTracking(); - var lidarrContent = _lidarrAlbumRepository.GetAll().AsNoTracking(); + var lidarrContent = _lidarrAlbumRepository.GetAll().Where(x => x.FullyAvailable).AsNoTracking(); var addedLog = _recentlyAddedLog.GetAll(); var addedPlexMovieLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).Select(x => x.ContentId); From 324c02a58d13516d8a05ae55bdbd97021e53fe01 Mon Sep 17 00:00:00 2001 From: Anojh Date: Sun, 7 Oct 2018 15:09:05 -0700 Subject: [PATCH 37/46] users can now remove their own requests --- .../app/requests/movierequests.component.html | 13 ++++++++----- .../app/requests/movierequests.component.ts | 7 +++++++ .../app/requests/music/musicrequests.component.html | 13 ++++++++----- .../app/requests/music/musicrequests.component.ts | 7 +++++++ .../app/requests/tvrequest-children.component.html | 4 +++- .../app/requests/tvrequest-children.component.ts | 8 ++++++++ .../app/requests/tvrequests.component.html | 2 +- .../ClientApp/app/requests/tvrequests.component.ts | 2 ++ 8 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index 05d0ca14f..a1dd5cadc 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -166,11 +166,7 @@
-
- -
+
+
-
- -
+
+
+
+ +
diff --git a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts index 19e941e9d..ff451e5b5 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts +++ b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts @@ -10,6 +10,7 @@ import { NotificationService, RequestService } from "../services"; export class TvRequestChildrenComponent { @Input() public childRequests: IChildRequests[]; @Input() public isAdmin: boolean; + @Input() public currentUser: string; @Output() public requestDeleted = new EventEmitter(); @@ -116,4 +117,11 @@ export class TvRequestChildrenComponent { this.childRequests.splice(index, 1); } } + + public isRequestUser(request: IChildRequests) { + if (request.requestedUser.userName === this.currentUser) { + return true; + } + return false; + } } diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.html b/src/Ombi/ClientApp/app/requests/tvrequests.component.html index 801998c71..7c5e13479 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.html @@ -99,7 +99,7 @@
- +

diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts index 144de0206..924fccd1f 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts @@ -20,6 +20,7 @@ export class TvRequestsComponent implements OnInit { public searchChanged = new Subject(); public searchText: string; public isAdmin: boolean; + public currentUser: string; public showChildDialogue = false; // This is for the child modal popup public selectedSeason: ITvRequests; public defaultPoster: string; @@ -48,6 +49,7 @@ export class TvRequestsComponent implements OnInit { private readonly platformLocation: PlatformLocation) { this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); + this.currentUser = this.auth.claims().name; if (this.isAdmin) { this.sonarrService.getQualityProfilesWithoutSettings() .subscribe(x => this.sonarrProfiles = x); From 5e0f04a2f67a177fd25fb73dac6cb5794ea2e9da Mon Sep 17 00:00:00 2001 From: Anojh Date: Sun, 7 Oct 2018 15:28:50 -0700 Subject: [PATCH 38/46] !wip - fix lint errors --- .../app/requests/movierequests.component.ts | 13 +++++++------ .../app/requests/music/musicrequests.component.ts | 13 +++++++------ .../app/requests/tvrequest-children.component.ts | 13 +++++++------ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index 950743dc4..19fc989f2 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -218,6 +218,13 @@ export class MovieRequestsComponent implements OnInit { }); } + public isRequestUser(request: IMovieRequests) { + if (request.requestedUser.userName === this.auth.claims().name) { + return true; + } + return false; + } + private filterActiveStyle(el: any) { el = el.toElement || el.relatedTarget || el.target || el.srcElement; @@ -366,10 +373,4 @@ export class MovieRequestsComponent implements OnInit { ("url(" + "https://image.tmdb.org/t/p/w1280" + req.background + ")"); } - public isRequestUser(request: IMovieRequests) { - if (request.requestedUser.userName === this.auth.claims().name) { - return true; - } - return false; - } } diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts index 360b68c27..e70d44a38 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts @@ -198,6 +198,13 @@ export class MusicRequestsComponent implements OnInit { this.loadInit(); } + public isRequestUser(request: IAlbumRequest) { + if (request.requestedUser.userName === this.auth.claims().name) { + return true; + } + return false; + } + // public subscribe(request: IAlbumRequest) { // request.subscribed = true; // this.requestService.subscribeToMovie(request.id) @@ -349,10 +356,4 @@ export class MusicRequestsComponent implements OnInit { ("url(" + req.cover + ")"); } - public isRequestUser(request: IAlbumRequest) { - if (request.requestedUser.userName === this.auth.claims().name) { - return true; - } - return false; - } } diff --git a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts index ff451e5b5..bc792a55b 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts +++ b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts @@ -111,6 +111,13 @@ export class TvRequestChildrenComponent { }); } + public isRequestUser(request: IChildRequests) { + if (request.requestedUser.userName === this.currentUser) { + return true; + } + return false; + } + private removeRequestFromUi(key: IChildRequests) { const index = this.childRequests.indexOf(key, 0); if (index > -1) { @@ -118,10 +125,4 @@ export class TvRequestChildrenComponent { } } - public isRequestUser(request: IChildRequests) { - if (request.requestedUser.userName === this.currentUser) { - return true; - } - return false; - } } From d9e25522e16f2be5ba8a1f7b95ff330f59f7b35a Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 8 Oct 2018 14:00:52 +0100 Subject: [PATCH 39/46] Fixed the issue where we could not delete users #2558 --- .../ClientApp/app/login/login.component.html | 2 +- .../usermanagement-user.component.html | 7 +- .../usermanagement.component.html | 2 +- .../createadmin/createadmin.component.html | 2 +- .../mediaserver/mediaserver.component.html | 2 +- .../app/wizard/welcome/welcome.component.html | 2 +- src/Ombi/cypress.json | 4 + src/Ombi/cypress/fixtures/example.json | 5 + src/Ombi/cypress/integration/login.spec.js | 38 ++ .../integration/usermanagement.spec.js | 48 ++ src/Ombi/cypress/integration/wizard.spec.js | 21 + src/Ombi/cypress/plugins/index.js | 17 + src/Ombi/cypress/support/commands.js | 25 + src/Ombi/cypress/support/index.js | 20 + src/Ombi/cypress/tsconfig.json | 12 + src/Ombi/package.json | 6 +- src/Ombi/yarn.lock | 597 +++++++++++++++++- 17 files changed, 776 insertions(+), 34 deletions(-) create mode 100644 src/Ombi/cypress.json create mode 100644 src/Ombi/cypress/fixtures/example.json create mode 100644 src/Ombi/cypress/integration/login.spec.js create mode 100644 src/Ombi/cypress/integration/usermanagement.spec.js create mode 100644 src/Ombi/cypress/integration/wizard.spec.js create mode 100644 src/Ombi/cypress/plugins/index.js create mode 100644 src/Ombi/cypress/support/commands.js create mode 100644 src/Ombi/cypress/support/index.js create mode 100644 src/Ombi/cypress/tsconfig.json diff --git a/src/Ombi/ClientApp/app/login/login.component.html b/src/Ombi/ClientApp/app/login/login.component.html index bb6afc1dd..5d5032aef 100644 --- a/src/Ombi/ClientApp/app/login/login.component.html +++ b/src/Ombi/ClientApp/app/login/login.component.html @@ -33,7 +33,7 @@ include the remember me checkbox - + diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index 6f3ae63ee..1dfba95dd 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -1,5 +1,8 @@ 

Create User

User: {{user.userName}}

+ + +
@@ -65,7 +68,7 @@
- +
@@ -208,7 +211,7 @@
- +
diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html index 8bbc5b45a..26faac5cb 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html @@ -2,7 +2,7 @@ - +
diff --git a/src/Ombi/ClientApp/app/wizard/createadmin/createadmin.component.html b/src/Ombi/ClientApp/app/wizard/createadmin/createadmin.component.html index bdb992a6e..2a7facaa5 100644 --- a/src/Ombi/ClientApp/app/wizard/createadmin/createadmin.component.html +++ b/src/Ombi/ClientApp/app/wizard/createadmin/createadmin.component.html @@ -19,7 +19,7 @@
- +
diff --git a/src/Ombi/ClientApp/app/wizard/mediaserver/mediaserver.component.html b/src/Ombi/ClientApp/app/wizard/mediaserver/mediaserver.component.html index 0973a2ad6..e6768328e 100644 --- a/src/Ombi/ClientApp/app/wizard/mediaserver/mediaserver.component.html +++ b/src/Ombi/ClientApp/app/wizard/mediaserver/mediaserver.component.html @@ -16,7 +16,7 @@
-
diff --git a/src/Ombi/ClientApp/app/wizard/welcome/welcome.component.html b/src/Ombi/ClientApp/app/wizard/welcome/welcome.component.html index 98cca17ef..8207583b6 100644 --- a/src/Ombi/ClientApp/app/wizard/welcome/welcome.component.html +++ b/src/Ombi/ClientApp/app/wizard/welcome/welcome.component.html @@ -9,7 +9,7 @@ we are just going to run though the initial Ombi setup!
- Next + Next
diff --git a/src/Ombi/cypress.json b/src/Ombi/cypress.json new file mode 100644 index 000000000..9310964db --- /dev/null +++ b/src/Ombi/cypress.json @@ -0,0 +1,4 @@ +{ + "projectId": "gms1wj", + "baseUrl": "http://localhost:3577" +} diff --git a/src/Ombi/cypress/fixtures/example.json b/src/Ombi/cypress/fixtures/example.json new file mode 100644 index 000000000..da18d9352 --- /dev/null +++ b/src/Ombi/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} \ No newline at end of file diff --git a/src/Ombi/cypress/integration/login.spec.js b/src/Ombi/cypress/integration/login.spec.js new file mode 100644 index 000000000..92f7eface --- /dev/null +++ b/src/Ombi/cypress/integration/login.spec.js @@ -0,0 +1,38 @@ +/// + +describe('Login Page', function () { + it('Invalid Password', function () { + cy.visit('/'); + cy.contains('Sign in'); + + cy.get('#inputEmail').type('automation'); + cy.get('#inputPassword').type('incorrectpw'); + + cy.get('[data-test=signinbtn]').click(); + cy.get('.ui-growl-title').should('be.visible'); + cy.get('.ui-growl-title').next().contains('Incorrect username') + }); + + it('Invalid Username', function () { + cy.visit('/'); + cy.contains('Sign in'); + + cy.get('#inputEmail').type('bad username'); + cy.get('#inputPassword').type('incorrectpw'); + + cy.get('[data-test=signinbtn]').click(); + cy.get('.ui-growl-title').should('be.visible'); + cy.get('.ui-growl-title').next().contains('Incorrect username') + }); + + it('Correct Login', function () { + cy.visit('/'); + cy.contains('Sign in'); + + cy.get('#inputEmail').type('automation'); + cy.get('#inputPassword').type('password'); + + cy.get('[data-test=signinbtn]').click(); + cy.url().should('include', '/search') + }); +}) \ No newline at end of file diff --git a/src/Ombi/cypress/integration/usermanagement.spec.js b/src/Ombi/cypress/integration/usermanagement.spec.js new file mode 100644 index 000000000..8c15f4593 --- /dev/null +++ b/src/Ombi/cypress/integration/usermanagement.spec.js @@ -0,0 +1,48 @@ +/// + +describe('User Management Page', function () { + beforeEach(function () { + cy.request({ + method: 'POST', + url: 'http://localhost:3577/api/v1/token', + body: { + username: 'automation', + password: 'password', + } + }) + .then((resp) => { + window.localStorage.setItem('id_token', resp.body.access_token) + }); + + cy.visit('/usermanagement'); + }); + + it('Loads users table', function () { + cy.contains("User Management"); + cy.contains("Add User To Ombi"); + }); + + it.only('Creates basic user', function(){ + cy.get('[data-test=adduserbtn').click(); + cy.url().should('include','/user'); + + // Setup the form + cy.get('#username').type("user1"); + cy.get('#alias').type("alias1"); + cy.get('#emailAddress').type("user1@emailaddress.com"); + cy.get('#password').type("password"); + cy.get('#confirmPass').type("password"); + + // setup the roles + cy.contains('Roles').click() + cy.get('#labelRequestTv').click(); + cy.get('#labelRequestMovie').click(); + + // submit user + cy.get('[data-test=createuserbtn]').click(); + + cy.get('.ui-growl-title').should('be.visible'); + cy.get('.ui-growl-title').next().contains('has been created successfully') + }); + +}) \ No newline at end of file diff --git a/src/Ombi/cypress/integration/wizard.spec.js b/src/Ombi/cypress/integration/wizard.spec.js new file mode 100644 index 000000000..d1487c8ca --- /dev/null +++ b/src/Ombi/cypress/integration/wizard.spec.js @@ -0,0 +1,21 @@ +describe('Wizard Setup Tests', function() { + it('Setup Wizard User', function() { + cy.visit('http://localhost:3577/'); + cy.url().should('include', '/Wizard') + + cy.get('[data-test=nextbtn]').click(); + + // Media server page + cy.contains('Please choose your media server'); + cy.get('[data-test=skipbtn]').click(); + + // Create user + cy.contains('Create the Admin account'); + cy.get('#adminUsername').type('automation'); + cy.get('#adminPassword').type('password'); + + // Submit user + cy.get('[data-test=createuserbtn]').click(); + cy.contains('Sign in'); + }) + }) \ No newline at end of file diff --git a/src/Ombi/cypress/plugins/index.js b/src/Ombi/cypress/plugins/index.js new file mode 100644 index 000000000..fd170fba6 --- /dev/null +++ b/src/Ombi/cypress/plugins/index.js @@ -0,0 +1,17 @@ +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +module.exports = (on, config) => { + // `on` is used to hook into various events Cypress emits + // `config` is the resolved Cypress config +} diff --git a/src/Ombi/cypress/support/commands.js b/src/Ombi/cypress/support/commands.js new file mode 100644 index 000000000..c1f5a772e --- /dev/null +++ b/src/Ombi/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add("login", (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This is will overwrite an existing command -- +// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/src/Ombi/cypress/support/index.js b/src/Ombi/cypress/support/index.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/src/Ombi/cypress/support/index.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/src/Ombi/cypress/tsconfig.json b/src/Ombi/cypress/tsconfig.json new file mode 100644 index 000000000..756a92b35 --- /dev/null +++ b/src/Ombi/cypress/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "allowJs": true, + "baseUrl": "../node_modules", + "types": [ + "cypress" + ] + }, + "include": [ + "**/*.*" + ] + } \ No newline at end of file diff --git a/src/Ombi/package.json b/src/Ombi/package.json index 5fac0c31a..4c5302d6c 100644 --- a/src/Ombi/package.json +++ b/src/Ombi/package.json @@ -7,7 +7,8 @@ "lint": "tslint -p .", "publish": "gulp publish", "restore": "dotnet restore && yarn install", - "clean": "gulp clean" + "clean": "gulp clean", + "cypress": "cypress open" }, "dependencies": { "@angular/animations": "^6.0.7", @@ -90,5 +91,8 @@ }, "resolutions": { "@types/tapable": "1.0.0" + }, + "devDependencies": { + "cypress": "^3.1.0" } } diff --git a/src/Ombi/yarn.lock b/src/Ombi/yarn.lock index 68381bf9d..1debb9f2d 100644 --- a/src/Ombi/yarn.lock +++ b/src/Ombi/yarn.lock @@ -100,6 +100,22 @@ dependencies: url "^0.11.0" +"@cypress/listr-verbose-renderer@0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a" + dependencies: + chalk "^1.1.3" + cli-cursor "^1.0.2" + date-fns "^1.27.2" + figures "^1.7.0" + +"@cypress/xvfb@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.3.tgz#6319afdcdcff7d1505daeeaa84484d0596189860" + dependencies: + debug "^3.1.0" + lodash.once "^4.1.1" + "@ng-bootstrap/ng-bootstrap@^2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-2.2.0.tgz#acd514e878a1412f39d50eff691095ecc0882bf3" @@ -128,20 +144,84 @@ dependencies: tslib "^1.9.0" +"@types/blob-util@1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@types/blob-util/-/blob-util-1.3.3.tgz#adba644ae34f88e1dd9a5864c66ad651caaf628a" + +"@types/bluebird@3.5.18": + version "3.5.18" + resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.18.tgz#6a60435d4663e290f3709898a4f75014f279c4d6" + +"@types/chai-jquery@1.1.35": + version "1.1.35" + resolved "https://registry.yarnpkg.com/@types/chai-jquery/-/chai-jquery-1.1.35.tgz#9a8f0a39ec0851b2768a8f8c764158c2a2568d04" + dependencies: + "@types/chai" "*" + "@types/jquery" "*" + +"@types/chai@*": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.6.tgz#1eb26c040e3a84205b1008ad55c800e5e8a94e34" + +"@types/chai@4.0.8": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.8.tgz#d27600e9ba2f371e08695d90a0fe0408d89c7be7" + "@types/core-js@^2.5.0": version "2.5.0" resolved "https://registry.yarnpkg.com/@types/core-js/-/core-js-2.5.0.tgz#35cc282488de6f10af1d92902899a3b8ca3fbc47" +"@types/jquery@*": + version "3.3.12" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.12.tgz#e83229bcbf09dc668f9d4c1894864199521ff258" + dependencies: + "@types/sizzle" "*" + +"@types/jquery@3.2.16": + version "3.2.16" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.2.16.tgz#04419c404a3194350e7d3f339a90e72c88db3111" + +"@types/lodash@4.14.87": + version "4.14.87" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.87.tgz#55f92183b048c2c64402afe472f8333f4e319a6b" + "@types/mini-css-extract-plugin@^0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-0.2.0.tgz#afb037dbbd76f6c13803927c2751d194188b5d47" dependencies: "@types/webpack" "*" +"@types/minimatch@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + +"@types/mocha@2.2.44": + version "2.2.44" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.44.tgz#1d4a798e53f35212fd5ad4d04050620171cd5b5e" + "@types/node@*", "@types/node@^10.5.1": version "10.5.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.1.tgz#d578446f4abff5c0b49ade9b4e5274f6badaadfc" +"@types/sinon-chai@2.7.29": + version "2.7.29" + resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-2.7.29.tgz#4db01497e2dd1908b2bd30d1782f456353f5f723" + dependencies: + "@types/chai" "*" + "@types/sinon" "*" + +"@types/sinon@*": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-5.0.4.tgz#a765b390b373cf01a3b19b0c97f9eb4bb2a168b1" + +"@types/sinon@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.0.0.tgz#9a93ffa4ee1329e85166278a5ed99f81dc4c8362" + +"@types/sizzle@*": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" + "@types/tapable@*", "@types/tapable@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.0.tgz#b76254453021be05681f6213416766bac9afb99c" @@ -356,6 +436,15 @@ ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + ajv@^6.1.0: version "6.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.2.tgz#678495f9b82f7cca6be248dd92f59bff5e1f4360" @@ -400,7 +489,7 @@ ansi-cyan@^0.1.1: dependencies: ansi-wrap "0.1.0" -ansi-escapes@^1.1.0: +ansi-escapes@^1.0.0, ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" @@ -612,6 +701,12 @@ async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" +async@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/async/-/async-2.4.0.tgz#4990200f18ea5b837c2cc4f8c031a6985c385611" + dependencies: + lodash "^4.14.0" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -648,10 +743,18 @@ aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + aws4@^1.2.1: version "1.7.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" +aws4@^1.6.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -668,7 +771,7 @@ babel-polyfill@6.23.0: core-js "^2.4.0" regenerator-runtime "^0.10.0" -babel-runtime@^6.22.0: +babel-runtime@^6.18.0, babel-runtime@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" dependencies: @@ -731,6 +834,10 @@ block-stream@*: dependencies: inherits "~2.0.0" +bluebird@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" + bluebird@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -861,6 +968,10 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: caniuse-db "^1.0.30000639" electron-to-chromium "^1.2.7" +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + buffer-from@^1.0.0, buffer-from@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04" @@ -921,6 +1032,12 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +cachedir@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-1.3.0.tgz#5e01928bf2d95b5edd94b0942188246740e0dbc4" + dependencies: + os-homedir "^1.0.1" + caller-id@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-id/-/caller-id-0.1.0.tgz#59bdac0893d12c3871408279231f97458364f07b" @@ -984,7 +1101,7 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.1: +chalk@2.4.1, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" dependencies: @@ -1000,6 +1117,10 @@ chardet@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.5.0.tgz#fe3ac73c00c3d865ffcc02a0682e2c20b6a06029" +check-more-types@2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" + check-types@^7.3.0: version "7.4.0" resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.4.0.tgz#0378ec1b9616ec71f774931a3c6516fad8c152f4" @@ -1048,6 +1169,10 @@ chrome-trace-event@^1.0.0: dependencies: tslib "^1.9.0" +ci-info@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -1076,12 +1201,29 @@ clean-css@4.1.x: dependencies: source-map "0.5.x" +cli-cursor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + dependencies: + restore-cursor "^1.0.1" + cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" dependencies: restore-cursor "^2.0.0" +cli-spinners@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" + +cli-truncate@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" + dependencies: + slice-ansi "0.0.4" + string-width "^1.0.1" + cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" @@ -1188,12 +1330,16 @@ colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" -combined-stream@^1.0.5, combined-stream@~1.0.5: +combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" dependencies: delayed-stream "~1.0.0" +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + commander@2.15.x, commander@~2.15.0: version "2.15.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" @@ -1206,6 +1352,12 @@ commander@~2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" +common-tags@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.4.0.tgz#1187be4f3d4cf0c0427d43f74eef1f73501614c0" + dependencies: + babel-runtime "^6.18.0" + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -1218,6 +1370,14 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" +concat-stream@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + concat-stream@^1.5.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" @@ -1345,7 +1505,7 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^6.0.5: +cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" dependencies: @@ -1475,6 +1635,51 @@ cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" +cypress@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.1.0.tgz#b718ba64289b887c7ab7a7f09245d871a4a409ba" + dependencies: + "@cypress/listr-verbose-renderer" "0.4.1" + "@cypress/xvfb" "1.2.3" + "@types/blob-util" "1.3.3" + "@types/bluebird" "3.5.18" + "@types/chai" "4.0.8" + "@types/chai-jquery" "1.1.35" + "@types/jquery" "3.2.16" + "@types/lodash" "4.14.87" + "@types/minimatch" "3.0.3" + "@types/mocha" "2.2.44" + "@types/sinon" "4.0.0" + "@types/sinon-chai" "2.7.29" + bluebird "3.5.0" + cachedir "1.3.0" + chalk "2.4.1" + check-more-types "2.24.0" + commander "2.11.0" + common-tags "1.4.0" + debug "3.1.0" + execa "0.10.0" + executable "4.1.1" + extract-zip "1.6.6" + fs-extra "4.0.1" + getos "3.1.0" + glob "7.1.2" + is-ci "1.0.10" + is-installed-globally "0.1.0" + lazy-ass "1.6.0" + listr "0.12.0" + lodash "4.17.10" + log-symbols "2.2.0" + minimist "1.2.0" + progress "1.1.8" + ramda "0.24.1" + request "2.87.0" + request-progress "0.3.1" + supports-color "5.1.0" + tmp "0.0.31" + url "0.11.0" + yauzl "2.8.0" + d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" @@ -1487,6 +1692,10 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +date-fns@^1.27.2: + version "1.29.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" + date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" @@ -1501,7 +1710,7 @@ debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@^3.1.0: +debug@3.1.0, debug@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: @@ -1669,6 +1878,10 @@ electron-to-chromium@^1.2.7: version "1.3.50" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.50.tgz#7438b76f92b41b919f3fbdd350fbd0757dacddf7" +elegant-spinner@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" + elliptic@^6.0.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" @@ -1821,6 +2034,18 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +execa@0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" + dependencies: + cross-spawn "^6.0.0" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" @@ -1833,6 +2058,16 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +executable@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" + dependencies: + pify "^2.2.0" + +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" @@ -1925,6 +2160,10 @@ extend@^3.0.0, extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" +extend@~3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + external-editor@^2.0.1: version "2.2.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" @@ -1960,6 +2199,15 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +extract-zip@1.6.6: + version "1.6.6" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.6.tgz#1290ede8d20d0872b429fd3f351ca128ec5ef85c" + dependencies: + concat-stream "1.6.0" + debug "2.6.9" + mkdirp "0.5.0" + yauzl "2.4.1" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -1992,6 +2240,19 @@ fastparse@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" +fd-slicer@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" + dependencies: + pend "~1.2.0" + +figures@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" @@ -2159,6 +2420,14 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" +form-data@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + dependencies: + asynckit "^0.4.0" + combined-stream "1.0.6" + mime-types "^2.1.12" + forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" @@ -2180,6 +2449,14 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" +fs-extra@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.1.tgz#7fc0c6c8957f983f57f306a24e5b9ddd8d0dd880" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^3.0.0" + universalify "^0.1.0" + fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" @@ -2270,6 +2547,12 @@ get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" +getos@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/getos/-/getos-3.1.0.tgz#db3aa4df15a3295557ce5e81aa9e3e5cdfaa6567" + dependencies: + async "2.4.0" + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -2319,6 +2602,17 @@ glob2base@^0.0.12: dependencies: find-index "^0.1.1" +glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^4.3.1: version "4.5.3" resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" @@ -2338,17 +2632,6 @@ glob@^6.0.4: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@~3.1.21: version "3.1.21" resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd" @@ -2357,6 +2640,12 @@ glob@~3.1.21: inherits "1" minimatch "~0.2.11" +global-dirs@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + dependencies: + ini "^1.3.4" + global-modules-path@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/global-modules-path/-/global-modules-path-2.1.0.tgz#923ec524e8726bb0c1a4ed4b8e21e1ff80c88bbb" @@ -2428,7 +2717,7 @@ graceful-fs@^3.0.0: dependencies: natives "^1.1.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -2507,6 +2796,10 @@ har-schema@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + har-validator@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" @@ -2523,6 +2816,13 @@ har-validator@~4.2.1: ajv "^4.9.1" har-schema "^1.0.5" +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -2533,6 +2833,10 @@ has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -2689,6 +2993,14 @@ http-signature@~1.1.0: jsprim "^1.2.2" sshpk "^1.7.0" +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" @@ -2752,6 +3064,10 @@ indent-string@^2.1.0: dependencies: repeating "^2.0.0" +indent-string@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" @@ -2874,6 +3190,12 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" +is-ci@1.0.10: + version "1.0.10" + resolved "http://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz#f739336b2632365061a9d48270cd56ae3369318e" + dependencies: + ci-info "^1.0.0" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -2964,6 +3286,13 @@ is-glob@^4.0.0: dependencies: is-extglob "^2.1.1" +is-installed-globally@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" + dependencies: + global-dirs "^0.1.0" + is-path-inside "^1.0.0" + is-my-ip-valid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" @@ -3160,6 +3489,12 @@ json5@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" +jsonfile@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -3201,6 +3536,10 @@ kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" +lazy-ass@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" + lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" @@ -3224,6 +3563,53 @@ liftoff@^2.1.0: rechoir "^0.6.2" resolve "^1.1.7" +listr-silent-renderer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" + +listr-update-renderer@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz#ca80e1779b4e70266807e8eed1ad6abe398550f9" + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + elegant-spinner "^1.0.1" + figures "^1.7.0" + indent-string "^3.0.0" + log-symbols "^1.0.2" + log-update "^1.0.2" + strip-ansi "^3.0.1" + +listr-verbose-renderer@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35" + dependencies: + chalk "^1.1.3" + cli-cursor "^1.0.2" + date-fns "^1.27.2" + figures "^1.7.0" + +listr@0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/listr/-/listr-0.12.0.tgz#6bce2c0f5603fa49580ea17cd6a00cc0e5fa451a" + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + figures "^1.7.0" + indent-string "^2.1.0" + is-promise "^2.1.0" + is-stream "^1.1.0" + listr-silent-renderer "^1.1.1" + listr-update-renderer "^0.2.0" + listr-verbose-renderer "^0.4.0" + log-symbols "^1.0.2" + log-update "^1.0.2" + ora "^0.2.3" + p-map "^1.1.1" + rxjs "^5.0.0-beta.11" + stream-to-observable "^0.1.0" + strip-ansi "^3.0.1" + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -3348,6 +3734,10 @@ lodash.mergewith@^4.6.0: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" +lodash.once@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" @@ -3394,20 +3784,37 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@^4.0.0, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@~4.17.10: +lodash@4.17.10, lodash@^4.0.0, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@~4.17.10: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" +lodash@^4.14.0: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + lodash@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" -log-symbols@^2.1.0: +log-symbols@2.2.0, log-symbols@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" dependencies: chalk "^2.0.1" +log-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" + dependencies: + chalk "^1.0.0" + +log-update@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1" + dependencies: + ansi-escapes "^1.0.0" + cli-cursor "^1.0.2" + loglevelnext@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-1.0.5.tgz#36fc4f5996d6640f539ff203ba819641680d75a2" @@ -3584,12 +3991,22 @@ mime-db@~1.33.0: version "1.33.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" +mime-db@~1.36.0: + version "1.36.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" + mime-types@^2.1.12, mime-types@~2.1.18, mime-types@~2.1.7: version "2.1.18" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" dependencies: mime-db "~1.33.0" +mime-types@~2.1.17: + version "2.1.20" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" + dependencies: + mime-db "~1.36.0" + mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" @@ -3687,6 +4104,12 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" +mkdirp@0.5.0: + version "0.5.0" + resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" + dependencies: + minimist "0.0.8" + "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" @@ -3981,7 +4404,7 @@ number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" -oauth-sign@~0.8.1: +oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" @@ -4067,6 +4490,10 @@ once@~1.3.0: dependencies: wrappy "1" +onetime@^1.0.0: + version "1.1.0" + resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" @@ -4095,6 +4522,15 @@ opn@4.0.2: object-assign "^4.0.1" pinkie-promise "^2.0.0" +ora@^0.2.3: + version "0.2.3" + resolved "http://registry.npmjs.org/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" + dependencies: + chalk "^1.1.1" + cli-cursor "^1.0.2" + cli-spinners "^0.1.2" + object-assign "^4.0.1" + orchestrator@^0.3.0: version "0.3.8" resolved "https://registry.yarnpkg.com/orchestrator/-/orchestrator-0.3.8.tgz#14e7e9e2764f7315fbac184e506c7aa6df94ad7e" @@ -4111,7 +4547,7 @@ os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" -os-homedir@^1.0.0: +os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -4129,7 +4565,7 @@ os-locale@^2.0.0: lcid "^1.0.0" mem "^1.1.0" -os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: +os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -4303,11 +4739,19 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" -pify@^2.0.0: +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +pify@^2.0.0, pify@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -4618,6 +5062,10 @@ process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" +progress@1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" @@ -4690,6 +5138,10 @@ qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" +qs@~6.5.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -4705,6 +5157,10 @@ querystring@0.2.0, querystring@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" +ramda@0.24.1: + version "0.24.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.24.1.tgz#c3b7755197f35b8dc3502228262c4c91ddb6b857" + randomatic@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.0.0.tgz#d35490030eb4f7578de292ce6dfb04a91a128923" @@ -4915,6 +5371,37 @@ replace-ext@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" +request-progress@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-0.3.1.tgz#0721c105d8a96ac6b2ce8b2c89ae2d5ecfcf6b3a" + dependencies: + throttleit "~0.0.2" + +request@2.87.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + "request@>=2.9.0 <2.82.0": version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" @@ -5006,6 +5493,13 @@ resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2: dependencies: path-parse "^1.0.5" +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + dependencies: + exit-hook "^1.0.0" + onetime "^1.0.0" + restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -5054,6 +5548,12 @@ rx@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" +rxjs@^5.0.0-beta.11: + version "5.5.12" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc" + dependencies: + symbol-observable "1.0.1" + rxjs@^6.0.0, rxjs@^6.1.0, rxjs@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.2.1.tgz#246cebec189a6cbc143a3ef9f62d6f4c91813ca1" @@ -5237,6 +5737,10 @@ slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -5439,6 +5943,10 @@ stream-shift@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" +stream-to-observable@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe" + strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" @@ -5518,6 +6026,12 @@ style-loader@^0.21.0: loader-utils "^1.1.0" schema-utils "^0.4.5" +supports-color@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.1.0.tgz#058a021d1b619f7ddf3980d712ea3590ce7de3d5" + dependencies: + has-flag "^2.0.0" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -5546,6 +6060,10 @@ svgo@^0.7.0: sax "~1.2.1" whet.extend "~0.9.9" +symbol-observable@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" + tapable@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.0.0.tgz#cbb639d9002eed9c6b5975eb20598d7936f1f9f2" @@ -5574,6 +6092,10 @@ text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" +throttleit@~0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf" + through2@^0.6.1: version "0.6.5" resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" @@ -5608,6 +6130,12 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +tmp@0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -5646,7 +6174,7 @@ to-string-loader@^1.1.5: dependencies: loader-utils "^0.2.16" -tough-cookie@~2.3.0: +tough-cookie@~2.3.0, tough-cookie@~2.3.3: version "2.3.4" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" dependencies: @@ -5822,6 +6350,10 @@ unique-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b" +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -5869,7 +6401,7 @@ url-loader@^1.0.1: mime "^2.0.3" schema-utils "^0.4.3" -url@^0.11.0: +url@0.11.0, url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" dependencies: @@ -6214,6 +6746,19 @@ yargs@^7.0.0: y18n "^3.2.1" yargs-parser "^5.0.0" +yauzl@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" + dependencies: + fd-slicer "~1.0.1" + +yauzl@2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.8.0.tgz#79450aff22b2a9c5a41ef54e02db907ccfbf9ee2" + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.0.1" + yn@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" From 8764ec3a78e6a452690528730edcf14817c61258 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Mon, 8 Oct 2018 16:11:01 +0100 Subject: [PATCH 40/46] More UI tests !wip --- .../usermanagement-user.component.html | 2 +- .../usermanagement.component.html | 2 +- src/Ombi/cypress/integration/login.spec.js | 6 +- .../integration/usermanagement.spec.js | 114 +++++++++++++++--- src/Ombi/cypress/support/commands.js | 34 ++++++ 5 files changed, 133 insertions(+), 25 deletions(-) diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index 1dfba95dd..c25102ba2 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -214,7 +214,7 @@
- + diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html index 26faac5cb..b8a89c2b3 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html @@ -129,7 +129,7 @@ Emby User - Details/Edit + Details/Edit diff --git a/src/Ombi/cypress/integration/login.spec.js b/src/Ombi/cypress/integration/login.spec.js index 92f7eface..af40f21e7 100644 --- a/src/Ombi/cypress/integration/login.spec.js +++ b/src/Ombi/cypress/integration/login.spec.js @@ -9,8 +9,7 @@ describe('Login Page', function () { cy.get('#inputPassword').type('incorrectpw'); cy.get('[data-test=signinbtn]').click(); - cy.get('.ui-growl-title').should('be.visible'); - cy.get('.ui-growl-title').next().contains('Incorrect username') + cy.verifyNotification('Incorrect username'); }); it('Invalid Username', function () { @@ -21,8 +20,7 @@ describe('Login Page', function () { cy.get('#inputPassword').type('incorrectpw'); cy.get('[data-test=signinbtn]').click(); - cy.get('.ui-growl-title').should('be.visible'); - cy.get('.ui-growl-title').next().contains('Incorrect username') + cy.verifyNotification('Incorrect username'); }); it('Correct Login', function () { diff --git a/src/Ombi/cypress/integration/usermanagement.spec.js b/src/Ombi/cypress/integration/usermanagement.spec.js index 8c15f4593..866542129 100644 --- a/src/Ombi/cypress/integration/usermanagement.spec.js +++ b/src/Ombi/cypress/integration/usermanagement.spec.js @@ -2,18 +2,12 @@ describe('User Management Page', function () { beforeEach(function () { - cy.request({ - method: 'POST', - url: 'http://localhost:3577/api/v1/token', - body: { - username: 'automation', - password: 'password', - } - }) - .then((resp) => { - window.localStorage.setItem('id_token', resp.body.access_token) - }); - + cy.login('automation', 'password'); + cy.createUser('userToDelete', 'password', [{ + value: "requestmovie", + Enabled: "true", + }]); + cy.visit('/usermanagement'); }); @@ -22,9 +16,9 @@ describe('User Management Page', function () { cy.contains("Add User To Ombi"); }); - it.only('Creates basic user', function(){ + it('Creates basic user', function () { cy.get('[data-test=adduserbtn').click(); - cy.url().should('include','/user'); + cy.url().should('include', '/user'); // Setup the form cy.get('#username').type("user1"); @@ -40,9 +34,91 @@ describe('User Management Page', function () { // submit user cy.get('[data-test=createuserbtn]').click(); - - cy.get('.ui-growl-title').should('be.visible'); - cy.get('.ui-growl-title').next().contains('has been created successfully') + + cy.verifyNotification('has been created successfully'); + + // Also check if the user is in the table + cy.contains('alias1'); }); - -}) \ No newline at end of file + + it('Tries to create user without roles', function () { + cy.get('[data-test=adduserbtn').click(); + cy.url().should('include', '/user'); + + // Setup the form + cy.get('#username').type("user1"); + cy.get('#alias').type("alias1"); + cy.get('#emailAddress').type("user1@emailaddress.com"); + cy.get('#password').type("password"); + cy.get('#confirmPass').type("password"); + + // submit user + cy.get('[data-test=createuserbtn]').click(); + + cy.verifyNotification('Please assign a role'); + + }); + + it('Tries to create user when passwords do not match', function () { + cy.get('[data-test=adduserbtn').click(); + cy.url().should('include', '/user'); + + // Setup the form + cy.get('#username').type("user1"); + cy.get('#alias').type("alias1"); + cy.get('#emailAddress').type("user1@emailaddress.com"); + cy.get('#password').type("password"); + cy.get('#confirmPass').type("pass22word"); + + // submit user + cy.get('[data-test=createuserbtn]').click(); + + cy.verifyNotification('Passwords do not match'); + }); + + it('Delete a user', function () { + cy.get('#edituserToDelete').click(); + cy.contains('User: userToDelete'); + cy.get('[data-test=deletebtn]').click(); + cy.contains('Are you sure that you want to delete this user?'); + cy.contains('Yes').click(); + cy.verifyNotification('was deleted'); + }) + + + it.only('Creates user with request limits', function () { + cy.get('[data-test=adduserbtn').click(); + cy.url().should('include', '/user'); + + // Setup the form + cy.get('#username').type("user2"); + cy.get('#alias').type("alias2"); + cy.get('#emailAddress').type("user2@emailaddress.com"); + cy.get('#password').type("password"); + cy.get('#confirmPass').type("password"); + + // setup the roles + cy.contains('Roles').click() + cy.get('#labelRequestMovie').click(); + + cy.contains('Request Limits').click(); + cy.get('#movieRequestLimit').clear().type(2); + cy.get('#musicRequestLimit').clear().type(3); + cy.get('#episodeRequestLimit').clear().type(4); + + // submit user + cy.get('[data-test=createuserbtn]').click(); + + cy.verifyNotification('has been updated successfully'); + + // Verify that the limits are set + cy.get('#edituser2').click(); + cy.contains('Request Limits').click(); + cy.get('#movieRequestLimit').should('eq', 2); + cy.get('#musicRequestLimit').should('eq', 3); + cy.get('#tvRequestLimit').should('eq', 4); + + }); + + +}); \ No newline at end of file diff --git a/src/Ombi/cypress/support/commands.js b/src/Ombi/cypress/support/commands.js index c1f5a772e..cc2110b3e 100644 --- a/src/Ombi/cypress/support/commands.js +++ b/src/Ombi/cypress/support/commands.js @@ -23,3 +23,37 @@ // // -- This is will overwrite an existing command -- // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) + +Cypress.Commands.add('login', (username, password) => { + cy.request({ + method: 'POST', + url: '/api/v1/token', + body: { + username: username, + password: password, + } + }) + .then((resp) => { + window.localStorage.setItem('id_token', resp.body.access_token) + }); +}); + +Cypress.Commands.add('createUser', (username, password, claims) => { + cy.request({ + method: 'POST', + url: '/api/v1/identity', + body: { + UserName: username, + Password: password, + Claims: claims, + }, + headers: { + 'Authorization': 'Bearer ' + window.localStorage.getItem('id_token'), + } + }) +}) + +Cypress.Commands.add('verifyNotification', (text) => { + cy.get('.ui-growl-title').should('be.visible'); + cy.get('.ui-growl-title').next().contains(text) +}) \ No newline at end of file From 148e39489629f1ac25ccfc58c0a5add977243397 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 8 Oct 2018 22:55:57 +0100 Subject: [PATCH 41/46] Added more UI test !wip --- src/Ombi/ClientApp/app/app.component.html | 4 +- .../updatedetails.component.html | 2 +- .../usermanagement-user.component.html | 6 +- .../integration/usermanagement.spec.js | 116 ++++++++++++++---- src/Ombi/cypress/support/commands.js | 2 +- src/Ombi/cypress/tsconfig.json | 12 -- src/Ombi/tsconfig.json | 4 + 7 files changed, 106 insertions(+), 40 deletions(-) delete mode 100644 src/Ombi/cypress/tsconfig.json diff --git a/src/Ombi/ClientApp/app/app.component.html b/src/Ombi/ClientApp/app/app.component.html index d695ac61c..9f6d00a7e 100644 --- a/src/Ombi/ClientApp/app/app.component.html +++ b/src/Ombi/ClientApp/app/app.component.html @@ -94,13 +94,13 @@
- +
diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index c25102ba2..3f44a808b 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -80,7 +80,7 @@
- +
@@ -132,7 +132,7 @@
-
@@ -213,7 +213,7 @@
- + diff --git a/src/Ombi/cypress/integration/usermanagement.spec.js b/src/Ombi/cypress/integration/usermanagement.spec.js index 866542129..0dcd53a6c 100644 --- a/src/Ombi/cypress/integration/usermanagement.spec.js +++ b/src/Ombi/cypress/integration/usermanagement.spec.js @@ -8,6 +8,11 @@ describe('User Management Page', function () { Enabled: "true", }]); + cy.createUser('userToEdit', 'password', [{ + value: "requestmovie", + Enabled: "true", + }]); + cy.visit('/usermanagement'); }); @@ -86,20 +91,8 @@ describe('User Management Page', function () { }) - it.only('Creates user with request limits', function () { - cy.get('[data-test=adduserbtn').click(); - cy.url().should('include', '/user'); - - // Setup the form - cy.get('#username').type("user2"); - cy.get('#alias').type("alias2"); - cy.get('#emailAddress').type("user2@emailaddress.com"); - cy.get('#password').type("password"); - cy.get('#confirmPass').type("password"); - - // setup the roles - cy.contains('Roles').click() - cy.get('#labelRequestMovie').click(); + it('Add request limits to a user', function () { + cy.get('#edituserToEdit').click(); cy.contains('Request Limits').click(); cy.get('#movieRequestLimit').clear().type(2); @@ -107,18 +100,99 @@ describe('User Management Page', function () { cy.get('#episodeRequestLimit').clear().type(4); // submit user - cy.get('[data-test=createuserbtn]').click(); + cy.get('[data-test=updatebtn]').click(); - cy.verifyNotification('has been updated successfully'); + cy.verifyNotification('successfully'); + + // Verify that the limits are set + cy.get('#edituserToEdit').click(); + cy.contains('Request Limits').click(); + cy.get('#movieRequestLimit').should('have.attr', 'ng-reflect-model', '2') + cy.get('#musicRequestLimit').should('have.attr', 'ng-reflect-model', '3') + cy.get('#episodeRequestLimit').should('have.attr', 'ng-reflect-model', '4') + + }); + + it('Add notification preferences to user', function () { + + cy.get('#edituserToEdit').click(); + + cy.contains('Notification Preferences').click(); + cy.get('[data-test=Discord]').clear().type("Discord"); + cy.get('[data-test=Pushbullet]').clear().type("Pushbullet"); + cy.get('[data-test=Pushover]').clear().type("Pushover"); + cy.get('[data-test=Telegram]').clear().type("Telegram"); + cy.get('[data-test=Slack]').clear().type("Slack"); + cy.get('[data-test=Mattermost]').clear().type("Mattermost"); + + // submit user + cy.get('[data-test=updatebtn]').click(); + + cy.verifyNotification('successfully'); + + // Verify that the limits are set + cy.get('#edituserToEdit').click(); + cy.contains('Notification Preferences').click(); + cy.get('[data-test=Discord]').should('have.attr', 'ng-reflect-model', "Discord"); + cy.get('[data-test=Pushbullet]').should('have.attr', 'ng-reflect-model', "Pushbullet"); + cy.get('[data-test=Pushover]').should('have.attr', 'ng-reflect-model', "Pushover"); + cy.get('[data-test=Telegram]').should('have.attr', 'ng-reflect-model', "Telegram"); + cy.get('[data-test=Slack]').should('have.attr', 'ng-reflect-model', "Slack"); + cy.get('[data-test=Mattermost]').should('have.attr', 'ng-reflect-model', "Mattermost"); + + }); + + it('Modify roles', function () { + + cy.get('#edituserToEdit').click(); + + cy.contains('Roles').click(); + cy.get('#labelRequestMovie').click(); + cy.get('#labelRequestTv').click(); + + // submit user + cy.get('[data-test=updatebtn]').click(); + + cy.verifyNotification('successfully'); // Verify that the limits are set - cy.get('#edituser2').click(); - cy.contains('Request Limits').click(); - cy.get('#movieRequestLimit').should('eq', 2); - cy.get('#musicRequestLimit').should('eq', 3); - cy.get('#tvRequestLimit').should('eq', 4); + cy.get('#edituserToEdit').click(); + cy.contains('Roles').click(); + cy.get('#createRequestMovie').should('have.attr', 'ng-reflect-model', 'true'); + cy.get('#createRequestTv').should('have.attr', 'ng-reflect-model', 'true'); + cy.get('#createDisabled').should('have.attr', 'ng-reflect-model', 'false'); }); + it('Update local users info', function () { + + cy.get('#userDropdown').click(); + cy.get('#updateUserDetails').click(); + + cy.url().should('include','/updatedetails'); + + cy.get('#emailAddress').clear().type("user11@emailaddress.com"); + cy.get('#currentPassword').type("password"); + + cy.get('[data-test=submitbtn]').click(); + + cy.verifyNotification('All of your details have now been updated'); + }); + + it('Update local users info with bad password', function () { + + cy.get('#userDropdown').click(); + cy.get('#updateUserDetails').click(); + + cy.url().should('include','/updatedetails'); + + cy.get('#emailAddress').clear().type("user11@emailaddress.com"); + cy.get('#currentPassword').type("password32113123123"); + + cy.get('[data-test=submitbtn]').click(); + + cy.verifyNotification('Your password is incorrect'); + }); + }); \ No newline at end of file diff --git a/src/Ombi/cypress/support/commands.js b/src/Ombi/cypress/support/commands.js index cc2110b3e..b44a1e2b5 100644 --- a/src/Ombi/cypress/support/commands.js +++ b/src/Ombi/cypress/support/commands.js @@ -56,4 +56,4 @@ Cypress.Commands.add('createUser', (username, password, claims) => { Cypress.Commands.add('verifyNotification', (text) => { cy.get('.ui-growl-title').should('be.visible'); cy.get('.ui-growl-title').next().contains(text) -}) \ No newline at end of file +}); diff --git a/src/Ombi/cypress/tsconfig.json b/src/Ombi/cypress/tsconfig.json deleted file mode 100644 index 756a92b35..000000000 --- a/src/Ombi/cypress/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "allowJs": true, - "baseUrl": "../node_modules", - "types": [ - "cypress" - ] - }, - "include": [ - "**/*.*" - ] - } \ No newline at end of file diff --git a/src/Ombi/tsconfig.json b/src/Ombi/tsconfig.json index 1256bed93..bd114dcdb 100644 --- a/src/Ombi/tsconfig.json +++ b/src/Ombi/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "target": "es5", "lib": [ + "es2015", "es2017", "dom" ], @@ -27,6 +28,9 @@ } ] }, + "types": [ + "cypress" + ], "include": [ "ClientApp/**/*", "typings/**/*", From 0b2b3d2f30d24d6e8a012ba352d95701c9306c2b Mon Sep 17 00:00:00 2001 From: Anojh Date: Tue, 9 Oct 2018 00:26:31 -0700 Subject: [PATCH 42/46] New role to enable users to remove their own requests --- src/Ombi.Helpers/OmbiRoles.cs | 1 + src/Ombi.Store/Context/OmbiContext.cs | 10 ++++++++++ src/Ombi/Attributes/UserAttribute.cs | 14 ++++++++++++++ .../requests/music/musicrequests.component.html | 2 +- src/Ombi/Controllers/IdentityController.cs | 1 + src/Ombi/Controllers/MusicRequestController.cs | 2 +- src/Ombi/Controllers/RequestController.cs | 6 +++--- 7 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 src/Ombi/Attributes/UserAttribute.cs diff --git a/src/Ombi.Helpers/OmbiRoles.cs b/src/Ombi.Helpers/OmbiRoles.cs index 1d584d57f..e0cfc5398 100644 --- a/src/Ombi.Helpers/OmbiRoles.cs +++ b/src/Ombi.Helpers/OmbiRoles.cs @@ -14,5 +14,6 @@ public const string RequestMusic = nameof(RequestMusic); public const string Disabled = nameof(Disabled); public const string ReceivesNewsletter = nameof(ReceivesNewsletter); + public const string ManageOwnRequests = nameof(ManageOwnRequests); } } \ No newline at end of file diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index 66631dfc6..54682e24e 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -145,6 +145,16 @@ namespace Ombi.Store.Context SaveChanges(); } + var manageOwnRequestsRole = Roles.Where(x => x.Name == OmbiRoles.ManageOwnRequests); + if (!manageOwnRequestsRole.Any()) + { + Roles.Add(new IdentityRole(OmbiRoles.ManageOwnRequests) + { + NormalizedName = OmbiRoles.ManageOwnRequests.ToUpper() + }); + SaveChanges(); + } + // Make sure we have the API User var apiUserExists = Users.Any(x => x.UserName.Equals("Api", StringComparison.CurrentCultureIgnoreCase)); if (!apiUserExists) diff --git a/src/Ombi/Attributes/UserAttribute.cs b/src/Ombi/Attributes/UserAttribute.cs new file mode 100644 index 000000000..3ab4cef49 --- /dev/null +++ b/src/Ombi/Attributes/UserAttribute.cs @@ -0,0 +1,14 @@ +using Microsoft.AspNetCore.Authorization; +using Ombi.Helpers; + + +namespace Ombi.Attributes +{ + public class UserAttribute : AuthorizeAttribute + { + public UserAttribute() + { + Roles = "ManageOwnRequests"; + } + } +} diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html index 28734f5a3..c4c903da2 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html @@ -186,7 +186,7 @@
-
+ diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index d138e973e..61b3f06d8 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -240,6 +240,7 @@ namespace Ombi.Controllers await CreateRole(OmbiRoles.RequestTv); await CreateRole(OmbiRoles.Disabled); await CreateRole(OmbiRoles.ReceivesNewsletter); + await CreateRole(OmbiRoles.ManageOwnRequests); } private async Task CreateRole(string role) diff --git a/src/Ombi/Controllers/MusicRequestController.cs b/src/Ombi/Controllers/MusicRequestController.cs index 0d763cd86..3ab99dc0f 100644 --- a/src/Ombi/Controllers/MusicRequestController.cs +++ b/src/Ombi/Controllers/MusicRequestController.cs @@ -88,7 +88,7 @@ namespace Ombi.Controllers /// The request identifier. /// [HttpDelete("{requestId:int}")] - [PowerUser] + [Authorize(Roles = "Admin,PowerUser,ManageOwnRequests")] public async Task DeleteRequest(int requestId) { await _engine.RemoveAlbumRequest(requestId); diff --git a/src/Ombi/Controllers/RequestController.cs b/src/Ombi/Controllers/RequestController.cs index 25270f9dd..a1a61c9f9 100644 --- a/src/Ombi/Controllers/RequestController.cs +++ b/src/Ombi/Controllers/RequestController.cs @@ -95,7 +95,7 @@ namespace Ombi.Controllers /// The request identifier. /// [HttpDelete("movie/{requestId:int}")] - [PowerUser] + [Authorize(Roles = "Admin,PowerUser,ManageOwnRequests")] public async Task DeleteRequest(int requestId) { await MovieRequestEngine.RemoveMovieRequest(requestId); @@ -269,7 +269,7 @@ namespace Ombi.Controllers /// The request identifier. /// [HttpDelete("tv/{requestId:int}")] - [PowerUser] + [Authorize(Roles = "Admin,PowerUser,ManageOwnRequests")] public async Task DeleteTvRequest(int requestId) { await TvRequestEngine.RemoveTvRequest(requestId); @@ -380,7 +380,7 @@ namespace Ombi.Controllers /// /// The model. /// - [PowerUser] + [Authorize(Roles = "Admin,PowerUser,ManageOwnRequests")] [HttpDelete("tv/child/{requestId:int}")] public async Task DeleteChildRequest(int requestId) { From 7e49366999b42989ba04476d2b5a10a89536008f Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 9 Oct 2018 19:30:58 +0100 Subject: [PATCH 43/46] !wip --- src/Ombi/cypress/integration/usermanagement.spec.js | 2 +- src/Ombi/package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/cypress/integration/usermanagement.spec.js b/src/Ombi/cypress/integration/usermanagement.spec.js index 866542129..3e6b83e28 100644 --- a/src/Ombi/cypress/integration/usermanagement.spec.js +++ b/src/Ombi/cypress/integration/usermanagement.spec.js @@ -109,7 +109,7 @@ describe('User Management Page', function () { // submit user cy.get('[data-test=createuserbtn]').click(); - cy.verifyNotification('has been updated successfully'); + cy.verifyNotification('has been created successfully'); // Verify that the limits are set cy.get('#edituser2').click(); diff --git a/src/Ombi/package.json b/src/Ombi/package.json index 4c5302d6c..ceb7fc621 100644 --- a/src/Ombi/package.json +++ b/src/Ombi/package.json @@ -4,6 +4,7 @@ "private": true, "scripts": { "vendor": "gulp vendor", + "main": "gulp main", "lint": "tslint -p .", "publish": "gulp publish", "restore": "dotnet restore && yarn install", From 65233cb3b7ded3fcdbc2436eaa8fe312407c4de9 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 9 Oct 2018 20:01:46 +0100 Subject: [PATCH 44/46] Fixed the issue where user preferences was not being inported into some notifications --- src/Ombi.Notifications/BaseNotification.cs | 20 ++++++++++++++++++- .../NotificationMessageCurlys.cs | 3 ++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Notifications/BaseNotification.cs b/src/Ombi.Notifications/BaseNotification.cs index d351c8283..53d6d5d9d 100644 --- a/src/Ombi.Notifications/BaseNotification.cs +++ b/src/Ombi.Notifications/BaseNotification.cs @@ -170,6 +170,24 @@ namespace Ombi.Notifications.Interfaces { return new NotificationMessageContent { Disabled = true }; } + + if (model.UserId.IsNullOrEmpty()) + { + if (model.RequestType == RequestType.Movie) + { + model.UserId = MovieRequest.RequestedUserId; + } + + if (model.RequestType == RequestType.Album) + { + model.UserId = AlbumRequest.RequestedUserId; + } + + if (model.RequestType == RequestType.TvShow) + { + model.UserId = TvRequest.RequestedUserId; + } + } var parsed = Parse(model, template, agent); return parsed; @@ -184,7 +202,7 @@ namespace Ombi.Notifications.Interfaces protected UserNotificationPreferences GetUserPreference(string userId, NotificationAgent agent) { return UserNotificationPreferences.GetAll() - .FirstOrDefault(x => x.Enabled && x.Agent == agent && x.UserId == userId); + .FirstOrDefault(x => x.Agent == agent && x.UserId == userId); } private NotificationMessageContent Parse(NotificationOptions model, NotificationTemplates template, NotificationAgent agent) diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 1b655b84d..b178f0545 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -19,7 +19,7 @@ namespace Ombi.Notifications LoadIssues(opts); if (pref != null) { - UserPreference = pref.Enabled ? pref.Value : string.Empty; + UserPreference = pref.Value; } string title; @@ -268,6 +268,7 @@ namespace Ombi.Notifications {nameof(IssueUser),IssueUser}, {nameof(UserName),UserName}, {nameof(Alias),Alias}, + {nameof(UserPreference),UserPreference}, }; } } \ No newline at end of file From 2fc0ab5fa8c632603943b45b449f3f610be59b82 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 9 Oct 2018 20:05:43 +0100 Subject: [PATCH 45/46] updated typescript !wip --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 862993a21..2d18fdcbb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,6 +3,7 @@ configuration: Release os: Visual Studio 2017 environment: nodejs_version: "9.8.0" + typescript_version: "3.0.1" install: # Get the latest stable version of Node.js or io.js From 48705f2ea09d744d001ffab07a1c9eef78557a5d Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 9 Oct 2018 20:20:06 +0100 Subject: [PATCH 46/46] another change !wip --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 2d18fdcbb..d8265e6f6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,6 +8,9 @@ environment: install: # Get the latest stable version of Node.js or io.js - ps: Install-Product node $env:nodejs_version + + - cmd: set path=%programfiles(x86)%\\Microsoft SDKs\TypeScript\2.2;%path% + - cmd: tsc -v build_script: - ps: ./build.ps1 --settings_skipverification=true