mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-11 07:46:05 -07:00
Email Notifications are now fully customizable and work! #865
We also have reactive forms in the UI, should apply this to other settings.
This commit is contained in:
parent
3b0b35f760
commit
9a4dbb3dce
21 changed files with 361 additions and 232 deletions
|
@ -1,4 +1,5 @@
|
||||||
using Ombi.Core.Claims;
|
using System;
|
||||||
|
using Ombi.Core.Claims;
|
||||||
using Ombi.Core.Models.Requests;
|
using Ombi.Core.Models.Requests;
|
||||||
using Ombi.Core.Rule;
|
using Ombi.Core.Rule;
|
||||||
using Ombi.Core.Rules;
|
using Ombi.Core.Rules;
|
||||||
|
@ -6,7 +7,12 @@ using Ombi.Store.Entities;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
|
using Hangfire;
|
||||||
|
using Ombi.Core.Models.Requests.Movie;
|
||||||
using Ombi.Core.Models.Search;
|
using Ombi.Core.Models.Search;
|
||||||
|
using Ombi.Core.Notifications;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Notifications.Models;
|
||||||
|
|
||||||
namespace Ombi.Core.Engine.Interfaces
|
namespace Ombi.Core.Engine.Interfaces
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
using Hangfire;
|
using Ombi.Api.TheMovieDb;
|
||||||
using Ombi.Api.TheMovieDb;
|
|
||||||
using Ombi.Core.Models.Requests;
|
using Ombi.Core.Models.Requests;
|
||||||
using Ombi.Core.Models.Requests.Movie;
|
using Ombi.Core.Models.Requests.Movie;
|
||||||
using Ombi.Core.Models.Search;
|
using Ombi.Core.Models.Search;
|
||||||
using Ombi.Core.Rules;
|
using Ombi.Core.Rules;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
using Ombi.Notifications;
|
using Ombi.Notifications;
|
||||||
using Ombi.Notifications.Models;
|
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -16,24 +14,22 @@ using System.Security.Principal;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Ombi.Core.Engine.Interfaces;
|
using Ombi.Core.Engine.Interfaces;
|
||||||
using Ombi.Core.Notifications;
|
|
||||||
using Ombi.Store;
|
|
||||||
|
|
||||||
namespace Ombi.Core.Engine
|
namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
public class MovieRequestEngine : BaseMediaEngine, IMovieRequestEngine
|
public class MovieRequestEngine : BaseMediaEngine, IMovieRequestEngine
|
||||||
{
|
{
|
||||||
public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user,
|
public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user,
|
||||||
INotificationService notificationService, IRuleEvaluator r, IMovieSender sender, ILogger<MovieRequestEngine> log) : base(user, requestService, r)
|
INotificationHelper helper, IRuleEvaluator r, IMovieSender sender, ILogger<MovieRequestEngine> log) : base(user, requestService, r)
|
||||||
{
|
{
|
||||||
MovieApi = movieApi;
|
MovieApi = movieApi;
|
||||||
NotificationService = notificationService;
|
NotificationHelper = helper;
|
||||||
Sender = sender;
|
Sender = sender;
|
||||||
Logger = log;
|
Logger = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IMovieDbApi MovieApi { get; }
|
private IMovieDbApi MovieApi { get; }
|
||||||
private INotificationService NotificationService { get; }
|
private INotificationHelper NotificationHelper { get; }
|
||||||
private IMovieSender Sender { get; }
|
private IMovieSender Sender { get; }
|
||||||
private ILogger<MovieRequestEngine> Logger { get; }
|
private ILogger<MovieRequestEngine> Logger { get; }
|
||||||
|
|
||||||
|
@ -84,6 +80,7 @@ namespace Ombi.Core.Engine
|
||||||
// });
|
// });
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
var requestModel = new MovieRequestModel
|
var requestModel = new MovieRequestModel
|
||||||
{
|
{
|
||||||
ProviderId = movieInfo.Id,
|
ProviderId = movieInfo.Id,
|
||||||
|
@ -98,64 +95,41 @@ namespace Ombi.Core.Engine
|
||||||
Status = movieInfo.Status,
|
Status = movieInfo.Status,
|
||||||
RequestedDate = DateTime.UtcNow,
|
RequestedDate = DateTime.UtcNow,
|
||||||
Approved = false,
|
Approved = false,
|
||||||
RequestedUser =Username,
|
RequestedUser = Username,
|
||||||
Issues = IssueState.None
|
Issues = IssueState.None
|
||||||
};
|
};
|
||||||
|
|
||||||
try
|
var ruleResults = RunRequestRules(requestModel).ToList();
|
||||||
|
if (ruleResults.Any(x => !x.Success))
|
||||||
{
|
{
|
||||||
var ruleResults = RunRequestRules(requestModel).ToList();
|
return new RequestEngineResult
|
||||||
if (ruleResults.Any(x => !x.Success))
|
{
|
||||||
|
ErrorMessage = ruleResults.FirstOrDefault(x => !string.IsNullOrEmpty(x.Message)).Message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestModel.Approved) // The rules have auto approved this
|
||||||
|
{
|
||||||
|
var result = await Sender.Send(requestModel);
|
||||||
|
if (result.Success && result.MovieSent)
|
||||||
|
{
|
||||||
|
return await AddMovieRequest(requestModel, /*settings,*/
|
||||||
|
$"{fullMovieName} has been successfully added!");
|
||||||
|
}
|
||||||
|
if (!result.Success)
|
||||||
|
{
|
||||||
|
Logger.LogWarning("Tried auto sending movie but failed. Message: {0}", result.Message);
|
||||||
return new RequestEngineResult
|
return new RequestEngineResult
|
||||||
{
|
{
|
||||||
ErrorMessage = ruleResults.FirstOrDefault(x => !string.IsNullOrEmpty(x.Message)).Message
|
Message = result.Message,
|
||||||
|
ErrorMessage = result.Message,
|
||||||
|
RequestAdded = false
|
||||||
};
|
};
|
||||||
|
|
||||||
if (requestModel.Approved) // The rules have auto approved this
|
|
||||||
{
|
|
||||||
var result = await Sender.Send(requestModel);
|
|
||||||
if (result.Success && result.MovieSent)
|
|
||||||
{
|
|
||||||
return await AddMovieRequest(requestModel, /*settings,*/
|
|
||||||
$"{fullMovieName} has been successfully added!");
|
|
||||||
}
|
|
||||||
if (!result.Success)
|
|
||||||
{
|
|
||||||
Logger.LogWarning("Tried auto sending movie but failed. Message: {0}", result.Message);
|
|
||||||
return new RequestEngineResult
|
|
||||||
{
|
|
||||||
Message = result.Message,
|
|
||||||
ErrorMessage = result.Message,
|
|
||||||
RequestAdded = false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return await AddMovieRequest(requestModel, /*settings,*/
|
|
||||||
$"{fullMovieName} has been successfully added!");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
//Log.Fatal(e);
|
|
||||||
//await FaultQueue.QueueItemAsync(model, movieInfo.Id.ToString(), RequestType.Movie, FaultType.RequestFault, e.Message);
|
|
||||||
var notification = new NotificationOptions
|
|
||||||
{
|
|
||||||
DateTime = DateTime.Now,
|
|
||||||
RequestedUser = Username,
|
|
||||||
RequestType = RequestType.Movie,
|
|
||||||
Title = model.Title,
|
|
||||||
NotificationType = NotificationType.ItemAddedToFaultQueue
|
|
||||||
};
|
|
||||||
BackgroundJob.Enqueue(() => NotificationService.Publish(notification).Wait());
|
|
||||||
|
|
||||||
//return Response.AsJson(new JsonResponseModel
|
|
||||||
//{
|
|
||||||
// Result = true,
|
|
||||||
// Message = $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}"
|
|
||||||
//});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return await AddMovieRequest(requestModel, /*settings,*/
|
||||||
|
$"{fullMovieName} has been successfully added!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<MovieRequestModel>> GetRequests(int count, int position)
|
public async Task<IEnumerable<MovieRequestModel>> GetRequests(int count, int position)
|
||||||
|
@ -210,21 +184,9 @@ namespace Ombi.Core.Engine
|
||||||
|
|
||||||
if (ShouldSendNotification(model.Type))
|
if (ShouldSendNotification(model.Type))
|
||||||
{
|
{
|
||||||
var notificationModel = new NotificationOptions
|
NotificationHelper.NewRequest(model);
|
||||||
{
|
|
||||||
Title = model.Title,
|
|
||||||
RequestedUser = Username,
|
|
||||||
DateTime = DateTime.Now,
|
|
||||||
NotificationType = NotificationType.NewRequest,
|
|
||||||
RequestType = model.Type,
|
|
||||||
ImgSrc = model.Type == RequestType.Movie
|
|
||||||
? $"https://image.tmdb.org/t/p/w300/{model.PosterPath}"
|
|
||||||
: model.PosterPath
|
|
||||||
};
|
|
||||||
|
|
||||||
BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel).Wait());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//var limit = await RequestLimitRepo.GetAllAsync();
|
//var limit = await RequestLimitRepo.GetAllAsync();
|
||||||
//var usersLimit = limit.FirstOrDefault(x => x.Username == Username && x.RequestType == model.Type);
|
//var usersLimit = limit.FirstOrDefault(x => x.Username == Username && x.RequestType == model.Type);
|
||||||
//if (usersLimit == null)
|
//if (usersLimit == null)
|
||||||
|
|
|
@ -15,23 +15,21 @@ using System.Linq;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Core.Engine.Interfaces;
|
using Ombi.Core.Engine.Interfaces;
|
||||||
using Ombi.Core.Notifications;
|
|
||||||
using Ombi.Store;
|
|
||||||
|
|
||||||
namespace Ombi.Core.Engine
|
namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
public class TvRequestEngine : BaseMediaEngine, ITvRequestEngine
|
public class TvRequestEngine : BaseMediaEngine, ITvRequestEngine
|
||||||
{
|
{
|
||||||
public TvRequestEngine(ITvMazeApi tvApi, IRequestServiceMain requestService, IPrincipal user,
|
public TvRequestEngine(ITvMazeApi tvApi, IRequestServiceMain requestService, IPrincipal user,
|
||||||
INotificationService notificationService, IMapper map,
|
INotificationHelper helper, IMapper map,
|
||||||
IRuleEvaluator rule) : base(user, requestService, rule)
|
IRuleEvaluator rule) : base(user, requestService, rule)
|
||||||
{
|
{
|
||||||
TvApi = tvApi;
|
TvApi = tvApi;
|
||||||
NotificationService = notificationService;
|
NotificationHelper = helper;
|
||||||
Mapper = map;
|
Mapper = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
private INotificationService NotificationService { get; }
|
private INotificationHelper NotificationHelper { get; }
|
||||||
private ITvMazeApi TvApi { get; }
|
private ITvMazeApi TvApi { get; }
|
||||||
private IMapper Mapper { get; }
|
private IMapper Mapper { get; }
|
||||||
|
|
||||||
|
@ -270,24 +268,11 @@ namespace Ombi.Core.Engine
|
||||||
return await AfterRequest(model);
|
return await AfterRequest(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<RequestEngineResult> AfterRequest(TvRequestModel model)
|
private Task<RequestEngineResult> AfterRequest(TvRequestModel model)
|
||||||
{
|
{
|
||||||
if (ShouldSendNotification(model.Type))
|
if (ShouldSendNotification(model.Type))
|
||||||
{
|
{
|
||||||
var n = new NotificationOptions();
|
NotificationHelper.NewRequest(model);
|
||||||
|
|
||||||
n.Title = model.Title;
|
|
||||||
n.RequestedUser = Username;
|
|
||||||
n.DateTime = DateTime.Now;
|
|
||||||
n.NotificationType = NotificationType.NewRequest;
|
|
||||||
n.RequestType = model.Type;
|
|
||||||
n.ImgSrc = model.PosterPath;
|
|
||||||
|
|
||||||
|
|
||||||
BackgroundJob.Enqueue(() =>
|
|
||||||
|
|
||||||
NotificationService.Publish(n).Wait()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//var limit = await RequestLimitRepo.GetAllAsync();
|
//var limit = await RequestLimitRepo.GetAllAsync();
|
||||||
|
@ -308,7 +293,7 @@ namespace Ombi.Core.Engine
|
||||||
// await RequestLimitRepo.UpdateAsync(usersLimit);
|
// await RequestLimitRepo.UpdateAsync(usersLimit);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
return new RequestEngineResult { RequestAdded = true };
|
return Task.FromResult(new RequestEngineResult { RequestAdded = true });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<TvRequestModel>> GetApprovedRequests()
|
public async Task<IEnumerable<TvRequestModel>> GetApprovedRequests()
|
||||||
|
|
9
src/Ombi.Core/INotificationHelper.cs
Normal file
9
src/Ombi.Core/INotificationHelper.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
using Ombi.Core.Models.Requests;
|
||||||
|
|
||||||
|
namespace Ombi.Core
|
||||||
|
{
|
||||||
|
public interface INotificationHelper
|
||||||
|
{
|
||||||
|
void NewRequest(BaseRequestModel model);
|
||||||
|
}
|
||||||
|
}
|
36
src/Ombi.Core/NotificationHelper.cs
Normal file
36
src/Ombi.Core/NotificationHelper.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
using System;
|
||||||
|
using Hangfire;
|
||||||
|
using Ombi.Core.Models.Requests;
|
||||||
|
using Ombi.Core.Notifications;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Notifications.Models;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
|
namespace Ombi.Core
|
||||||
|
{
|
||||||
|
public class NotificationHelper : INotificationHelper
|
||||||
|
{
|
||||||
|
public NotificationHelper(INotificationService service)
|
||||||
|
{
|
||||||
|
NotificationService = service;
|
||||||
|
}
|
||||||
|
private INotificationService NotificationService { get; }
|
||||||
|
|
||||||
|
public void NewRequest(BaseRequestModel model)
|
||||||
|
{
|
||||||
|
var notificationModel = new NotificationOptions
|
||||||
|
{
|
||||||
|
Title = model.Title,
|
||||||
|
RequestedUser = model.RequestedUser,
|
||||||
|
DateTime = DateTime.Now,
|
||||||
|
NotificationType = NotificationType.NewRequest,
|
||||||
|
RequestType = model.Type,
|
||||||
|
ImgSrc = model.Type == RequestType.Movie
|
||||||
|
? $"https://image.tmdb.org/t/p/w300/{model.PosterPath}"
|
||||||
|
: model.PosterPath
|
||||||
|
};
|
||||||
|
BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -84,6 +84,7 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddTransient<IRequestServiceMain, RequestService>();
|
services.AddTransient<IRequestServiceMain, RequestService>();
|
||||||
services.AddTransient(typeof(IRequestService<>), typeof(JsonRequestService<>));
|
services.AddTransient(typeof(IRequestService<>), typeof(JsonRequestService<>));
|
||||||
services.AddSingleton<INotificationService, NotificationService>();
|
services.AddSingleton<INotificationService, NotificationService>();
|
||||||
|
services.AddSingleton<INotificationHelper, NotificationHelper>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RegisterJobs(this IServiceCollection services)
|
public static void RegisterJobs(this IServiceCollection services)
|
||||||
|
|
|
@ -40,31 +40,43 @@ namespace Ombi.Notifications.Agents
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<NotificationMessageContent> LoadTemplate(NotificationType type, NotificationOptions model)
|
private async Task<NotificationMessage> LoadTemplate(NotificationType type, NotificationOptions model, EmailNotificationSettings settings)
|
||||||
{
|
{
|
||||||
var template = await TemplateRepository.GetTemplate(NotificationAgent.Email, type);
|
var template = await TemplateRepository.GetTemplate(NotificationAgent.Email, type);
|
||||||
|
if (!template.Enabled)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
// Need to do the parsing
|
// Need to do the parsing
|
||||||
var resolver = new NotificationMessageResolver();
|
var resolver = new NotificationMessageResolver();
|
||||||
return resolver.ParseMessage(template, new NotificationMessageCurlys(model.RequestedUser, model.Title, DateTime.Now.ToString("D"),
|
var parsed = resolver.ParseMessage(template, new NotificationMessageCurlys(model.RequestedUser, model.Title, DateTime.Now.ToString("D"),
|
||||||
model.NotificationType.ToString(), null));
|
model.NotificationType.ToString(), null));
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task NewRequest(NotificationOptions model, EmailNotificationSettings settings)
|
|
||||||
{
|
|
||||||
var template = await LoadTemplate(NotificationType.NewRequest, model);
|
|
||||||
|
|
||||||
var email = new EmailBasicTemplate();
|
var email = new EmailBasicTemplate();
|
||||||
var html = email.LoadTemplate(template.Subject, template.Message, model.ImgSrc);
|
var html = email.LoadTemplate(parsed.Subject, parsed.Message, model.ImgSrc);
|
||||||
|
|
||||||
|
|
||||||
var message = new NotificationMessage
|
var message = new NotificationMessage
|
||||||
{
|
{
|
||||||
Message = html,
|
Message = html,
|
||||||
Subject = $"Ombi: New {model.RequestType} request for {model.Title}!",
|
Subject = parsed.Subject,
|
||||||
To = settings.AdminEmail,
|
To = settings.AdminEmail,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected override async Task NewRequest(NotificationOptions model, EmailNotificationSettings settings)
|
||||||
|
{
|
||||||
|
var message = await LoadTemplate(NotificationType.NewRequest, model, settings);
|
||||||
|
if (message == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
message.Other.Add("PlainTextBody", $"Hello! The user '{model.RequestedUser}' has requested the {model.RequestType} '{model.Title}'! Please log in to approve this request. Request Date: {model.DateTime:f}");
|
message.Other.Add("PlainTextBody", $"Hello! The user '{model.RequestedUser}' has requested the {model.RequestType} '{model.Title}'! Please log in to approve this request. Request Date: {model.DateTime:f}");
|
||||||
|
|
||||||
await Send(message, settings);
|
await Send(message, settings);
|
||||||
|
@ -72,18 +84,11 @@ namespace Ombi.Notifications.Agents
|
||||||
|
|
||||||
protected override async Task Issue(NotificationOptions model, EmailNotificationSettings settings)
|
protected override async Task Issue(NotificationOptions model, EmailNotificationSettings settings)
|
||||||
{
|
{
|
||||||
var email = new EmailBasicTemplate();
|
var message = await LoadTemplate(NotificationType.Issue, model, settings);
|
||||||
var html = email.LoadTemplate(
|
if (message == null)
|
||||||
$"Ombi: New issue for {model.Title}!",
|
|
||||||
$"Hello! The user '{model.RequestedUser}' has reported a new issue {model.Body} for the title {model.Title}!",
|
|
||||||
model.ImgSrc);
|
|
||||||
|
|
||||||
var message = new NotificationMessage
|
|
||||||
{
|
{
|
||||||
Message = html,
|
return;
|
||||||
Subject = $"Ombi: New issue for {model.Title}!",
|
}
|
||||||
To = settings.AdminEmail,
|
|
||||||
};
|
|
||||||
|
|
||||||
message.Other.Add("PlainTextBody", $"Hello! The user '{model.RequestedUser}' has reported a new issue {model.Body} for the title {model.Title}!");
|
message.Other.Add("PlainTextBody", $"Hello! The user '{model.RequestedUser}' has reported a new issue {model.Body} for the title {model.Title}!");
|
||||||
|
|
||||||
|
@ -113,18 +118,11 @@ namespace Ombi.Notifications.Agents
|
||||||
|
|
||||||
protected override async Task RequestDeclined(NotificationOptions model, EmailNotificationSettings settings)
|
protected override async Task RequestDeclined(NotificationOptions model, EmailNotificationSettings settings)
|
||||||
{
|
{
|
||||||
var email = new EmailBasicTemplate();
|
var message = await LoadTemplate(NotificationType.RequestDeclined, model, settings);
|
||||||
var html = email.LoadTemplate(
|
if (message == null)
|
||||||
"Ombi: Your request has been declined",
|
|
||||||
$"Hello! Your request for {model.Title} has been declined, Sorry!",
|
|
||||||
model.ImgSrc);
|
|
||||||
|
|
||||||
var message = new NotificationMessage
|
|
||||||
{
|
{
|
||||||
Message = html,
|
return;
|
||||||
Subject = $"Ombi: Your request has been declined",
|
}
|
||||||
To = model.UserEmail,
|
|
||||||
};
|
|
||||||
|
|
||||||
message.Other.Add("PlainTextBody", $"Hello! Your request for {model.Title} has been declined, Sorry!");
|
message.Other.Add("PlainTextBody", $"Hello! Your request for {model.Title} has been declined, Sorry!");
|
||||||
|
|
||||||
|
@ -134,18 +132,11 @@ namespace Ombi.Notifications.Agents
|
||||||
|
|
||||||
protected override async Task RequestApproved(NotificationOptions model, EmailNotificationSettings settings)
|
protected override async Task RequestApproved(NotificationOptions model, EmailNotificationSettings settings)
|
||||||
{
|
{
|
||||||
var email = new EmailBasicTemplate();
|
var message = await LoadTemplate(NotificationType.RequestApproved, model, settings);
|
||||||
var html = email.LoadTemplate(
|
if (message == null)
|
||||||
"Ombi: Your request has been approved!",
|
|
||||||
$"Hello! Your request for {model.Title} has been approved!",
|
|
||||||
model.ImgSrc);
|
|
||||||
|
|
||||||
var message = new NotificationMessage
|
|
||||||
{
|
{
|
||||||
Message = html,
|
return;
|
||||||
Subject = $"Ombi: Your request has been approved!",
|
}
|
||||||
To = model.UserEmail,
|
|
||||||
};
|
|
||||||
|
|
||||||
message.Other.Add("PlainTextBody", $"Hello! Your request for {model.Title} has been approved!");
|
message.Other.Add("PlainTextBody", $"Hello! Your request for {model.Title} has been approved!");
|
||||||
|
|
||||||
|
@ -154,19 +145,11 @@ namespace Ombi.Notifications.Agents
|
||||||
|
|
||||||
protected override async Task AvailableRequest(NotificationOptions model, EmailNotificationSettings settings)
|
protected override async Task AvailableRequest(NotificationOptions model, EmailNotificationSettings settings)
|
||||||
{
|
{
|
||||||
var email = new EmailBasicTemplate();
|
var message = await LoadTemplate(NotificationType.RequestAvailable, model, settings);
|
||||||
var html = email.LoadTemplate(
|
if (message == null)
|
||||||
$"Ombi: {model.Title} is now available!",
|
|
||||||
$"Hello! You requested {model.Title} on Ombi! This is now available on Plex! :)",
|
|
||||||
model.ImgSrc);
|
|
||||||
|
|
||||||
|
|
||||||
var message = new NotificationMessage
|
|
||||||
{
|
{
|
||||||
Message = html,
|
return;
|
||||||
Subject = $"Ombi: {model.Title} is now available!",
|
}
|
||||||
To = model.UserEmail,
|
|
||||||
};
|
|
||||||
|
|
||||||
message.Other.Add("PlainTextBody", $"Hello! You requested {model.Title} on Ombi! This is now available on Plex! :)");
|
message.Other.Add("PlainTextBody", $"Hello! You requested {model.Title} on Ombi! This is now available on Plex! :)");
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Core.Settings;
|
using Ombi.Core.Settings;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
using Ombi.Notifications.Models;
|
using Ombi.Notifications.Models;
|
||||||
using Ombi.Store;
|
using Ombi.Store;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
using Ombi.Store.Repository;
|
using Ombi.Store.Repository;
|
||||||
|
|
||||||
namespace Ombi.Notifications
|
namespace Ombi.Notifications
|
||||||
|
@ -36,7 +39,6 @@ namespace Ombi.Notifications
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
switch (model.NotificationType)
|
switch (model.NotificationType)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
namespace Ombi.Notifications
|
namespace Ombi.Notifications
|
||||||
|
@ -18,19 +19,31 @@ namespace Ombi.Notifications
|
||||||
Type = type;
|
Type = type;
|
||||||
Issue = issue;
|
Issue = issue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// User Defined
|
||||||
private string RequestedUser { get; }
|
private string RequestedUser { get; }
|
||||||
private string Title { get; }
|
private string Title { get; }
|
||||||
private string RequestedDate { get; }
|
private string RequestedDate { get; }
|
||||||
private string Type { get; }
|
private string Type { get; }
|
||||||
private string Issue { get; }
|
private string Issue { get; }
|
||||||
|
|
||||||
|
// System Defined
|
||||||
|
private string LongDate => DateTime.Now.ToString("D");
|
||||||
|
private string ShortDate => DateTime.Now.ToString("d");
|
||||||
|
private string LongTime => DateTime.Now.ToString("T");
|
||||||
|
private string ShortTime => DateTime.Now.ToString("t");
|
||||||
|
|
||||||
public Dictionary<string, string> Curlys => new Dictionary<string, string>
|
public Dictionary<string, string> Curlys => new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
{nameof(RequestedUser), RequestedUser },
|
{nameof(RequestedUser), RequestedUser },
|
||||||
{nameof(Title), Title },
|
{nameof(Title), Title },
|
||||||
{nameof(RequestedDate), RequestedDate },
|
{nameof(RequestedDate), RequestedDate },
|
||||||
{nameof(Type), Type },
|
{nameof(Type), Type },
|
||||||
{nameof(Issue), Issue }
|
{nameof(Issue), Issue },
|
||||||
|
{nameof(LongDate),LongDate},
|
||||||
|
{nameof(ShortDate),ShortDate},
|
||||||
|
{nameof(LongTime),LongTime},
|
||||||
|
{nameof(ShortTime),ShortTime},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
|
@ -64,25 +63,27 @@ namespace Ombi.Store.Context
|
||||||
{
|
{
|
||||||
foreach (var notificationType in allTypes)
|
foreach (var notificationType in allTypes)
|
||||||
{
|
{
|
||||||
var notificationToAdd = new NotificationTemplates();
|
NotificationTemplates notificationToAdd;
|
||||||
switch (notificationType)
|
switch (notificationType)
|
||||||
{
|
{
|
||||||
case NotificationType.NewRequest:
|
case NotificationType.NewRequest:
|
||||||
notificationToAdd = new NotificationTemplates
|
notificationToAdd = new NotificationTemplates
|
||||||
{
|
{
|
||||||
NotificationType = notificationType,
|
NotificationType = notificationType,
|
||||||
Message = "Hello! The user '{requestedUser}' has requested the {Type} '{Title}'! Please log in to approve this request. Request Date: {RequestedDate}",
|
Message = "Hello! The user '{RequestedUser}' has requested the {Type} '{Title}'! Please log in to approve this request. Request Date: {RequestedDate}",
|
||||||
Subject = "Ombi: New {Type} request for {Title}!",
|
Subject = "Ombi: New {Type} request for {Title}!",
|
||||||
Agent = agent,
|
Agent = agent,
|
||||||
|
Enabled = true,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case NotificationType.Issue:
|
case NotificationType.Issue:
|
||||||
notificationToAdd = new NotificationTemplates
|
notificationToAdd = new NotificationTemplates
|
||||||
{
|
{
|
||||||
NotificationType = notificationType,
|
NotificationType = notificationType,
|
||||||
Message = "Hello! The user '{requestedUser}' has reported a new issue for the title {Title}! </br> {Issue}",
|
Message = "Hello! The user '{RequestedUser}' has reported a new issue for the title {Title}! </br> {Issue}",
|
||||||
Subject = "Ombi: New issue for {Title}!",
|
Subject = "Ombi: New issue for {Title}!",
|
||||||
Agent = agent,
|
Agent = agent,
|
||||||
|
Enabled = true,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case NotificationType.RequestAvailable:
|
case NotificationType.RequestAvailable:
|
||||||
|
@ -92,6 +93,7 @@ namespace Ombi.Store.Context
|
||||||
Message = "Hello! You requested {Title} on Ombi! This is now available! :)",
|
Message = "Hello! You requested {Title} on Ombi! This is now available! :)",
|
||||||
Subject = "Ombi: {Title} is now available!",
|
Subject = "Ombi: {Title} is now available!",
|
||||||
Agent = agent,
|
Agent = agent,
|
||||||
|
Enabled = true,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case NotificationType.RequestApproved:
|
case NotificationType.RequestApproved:
|
||||||
|
@ -101,6 +103,7 @@ namespace Ombi.Store.Context
|
||||||
Message = "Hello! Your request for {Title} has been approved!",
|
Message = "Hello! Your request for {Title} has been approved!",
|
||||||
Subject = "Ombi: your request has been approved",
|
Subject = "Ombi: your request has been approved",
|
||||||
Agent = agent,
|
Agent = agent,
|
||||||
|
Enabled = true,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case NotificationType.AdminNote:
|
case NotificationType.AdminNote:
|
||||||
|
@ -110,12 +113,11 @@ namespace Ombi.Store.Context
|
||||||
case NotificationType.RequestDeclined:
|
case NotificationType.RequestDeclined:
|
||||||
notificationToAdd = new NotificationTemplates
|
notificationToAdd = new NotificationTemplates
|
||||||
{
|
{
|
||||||
//"Ombi: Your request has been declined",
|
|
||||||
//$"Hello! Your request for {model.Title} has been declined, Sorry!",
|
|
||||||
NotificationType = notificationType,
|
NotificationType = notificationType,
|
||||||
Message = "Hello! Your request for {Title} has been declined, Sorry!",
|
Message = "Hello! Your request for {Title} has been declined, Sorry!",
|
||||||
Subject = "Ombi: your request has been declined",
|
Subject = "Ombi: your request has been declined",
|
||||||
Agent = agent,
|
Agent = agent,
|
||||||
|
Enabled = true,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case NotificationType.ItemAddedToFaultQueue:
|
case NotificationType.ItemAddedToFaultQueue:
|
||||||
|
|
|
@ -10,5 +10,6 @@ namespace Ombi.Store.Entities
|
||||||
public NotificationAgent Agent { get; set; }
|
public NotificationAgent Agent { get; set; }
|
||||||
public string Subject { get; set; }
|
public string Subject { get; set; }
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
|
public bool Enabled { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -72,6 +72,7 @@ CREATE TABLE IF NOT EXISTS NotificationTemplates
|
||||||
NotificationType INTEGER NOT NULL,
|
NotificationType INTEGER NOT NULL,
|
||||||
Agent INTEGER NOT NULL,
|
Agent INTEGER NOT NULL,
|
||||||
Subject BLOB NULL,
|
Subject BLOB NULL,
|
||||||
Message BLOB NULL
|
Message BLOB NULL,
|
||||||
|
Enabled INTEGER NOT NULL
|
||||||
|
|
||||||
);
|
);
|
|
@ -14,19 +14,17 @@ import { ICustomizationSettings } from './interfaces/ISettings';
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
|
|
||||||
constructor(public notificationService: NotificationService, public authService: AuthService, private router: Router, private settingsService: SettingsService
|
constructor(public notificationService: NotificationService, public authService: AuthService, private router: Router, private settingsService: SettingsService)
|
||||||
) {
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
customizationSettings: ICustomizationSettings;
|
customizationSettings: ICustomizationSettings;
|
||||||
user: ILocalUser;
|
user: ILocalUser;
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit() : void {
|
||||||
|
|
||||||
this.user = this.authService.claims();
|
this.user = this.authService.claims();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x);
|
this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x);
|
||||||
|
|
||||||
this.router.events.subscribe(() => {
|
this.router.events.subscribe(() => {
|
||||||
|
@ -34,7 +32,6 @@ export class AppComponent implements OnInit {
|
||||||
this.user = this.authService.claims();
|
this.user = this.authService.claims();
|
||||||
this.showNav = this.authService.loggedIn();
|
this.showNav = this.authService.loggedIn();
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasRole(role: string): boolean {
|
hasRole(role: string): boolean {
|
||||||
|
|
|
@ -22,6 +22,7 @@ export interface INotificationTemplates {
|
||||||
message: string,
|
message: string,
|
||||||
notificationType: NotificationType,
|
notificationType: NotificationType,
|
||||||
notificationAgent: NotificationAgent,
|
notificationAgent: NotificationAgent,
|
||||||
|
enabled:boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum NotificationAgent {
|
export enum NotificationAgent {
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { FormGroup, Validators, ValidatorFn } from '@angular/forms';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ValidationService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable validation on a control
|
||||||
|
* @param form
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
public disableValidation(form: FormGroup, name: string): void {
|
||||||
|
form.controls[name].clearValidators();
|
||||||
|
form.controls[name].updateValueAndValidity();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable validation with the default validation attribute of required
|
||||||
|
* @param form
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
public enableValidation(form: FormGroup, name: string): void;
|
||||||
|
public enableValidation(form: FormGroup, name: string, validators?: ValidatorFn[]): void {
|
||||||
|
if (validators) {
|
||||||
|
// If we provide some use them
|
||||||
|
form.controls[name].setValidators(validators);
|
||||||
|
} else {
|
||||||
|
// It's just required by default
|
||||||
|
form.controls[name].setValidators([Validators.required]);
|
||||||
|
}
|
||||||
|
form.controls[name].updateValueAndValidity();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,82 +1,99 @@
|
||||||
|
|
||||||
<settings-menu></settings-menu>
|
<settings-menu></settings-menu>
|
||||||
<div *ngIf="settings">
|
<div *ngIf="emailForm">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Email Notifications</legend>
|
<legend>Email Notifications</legend>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="form-group">
|
<form novalidate [formGroup]="emailForm" (ngSubmit)="onSubmit(emailForm)">
|
||||||
<div class="checkbox">
|
|
||||||
<input type="checkbox" id="enable" [(ngModel)]="settings.enabled" ng-checked="settings.enabled">
|
<div class="form-group">
|
||||||
<label for="enable">Enabled</label>
|
<div class="checkbox">
|
||||||
|
<input type="checkbox" id="enable" formControlName="enabled">
|
||||||
|
<label for="enable">Enabled</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<input type="checkbox" id="Authentication" [(ngModel)]="settings.authentication" ng-checked="settings.authentication"><label for="Authentication">Enable SMTP Authentication</label>
|
<input type="checkbox" id="Authentication" formControlName="authentication"><label for="Authentication">Enable SMTP Authentication</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div *ngIf="emailForm.invalid && emailForm.dirty" class="alert alert-danger">
|
||||||
|
<div *ngIf="emailForm.get('host').hasError('required')">Host is required</div>
|
||||||
<div class="form-group">
|
<div *ngIf="emailForm.get('port').hasError('required')">The Port is required</div>
|
||||||
<label for="host" class="control-label">SMTP Host</label>
|
<div *ngIf="emailForm.get('sender').hasError('required')">The Email Sender is required</div>
|
||||||
<div>
|
<div *ngIf="emailForm.get('sender').hasError('email')">The Email Sender needs to be a valid email address</div>
|
||||||
<input type="text" class="form-control form-control-custom " id="host" name="host" placeholder="localhost" [(ngModel)]="settings.host" value="{{settings.host}}">
|
<div *ngIf="emailForm.get('adminEmail').hasError('required')">The Email Sender is required</div>
|
||||||
|
<div *ngIf="emailForm.get('adminEmail').hasError('email')">The Admin Email needs to be a valid email address</div>
|
||||||
|
<div *ngIf="emailForm.get('username').hasError('required')">The Username is required</div>
|
||||||
|
<div *ngIf="emailForm.get('password').hasError('required')">The Password is required</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="portNumber" class="control-label">SMTP Port</label>
|
<label for="host" class="control-label">SMTP Host</label>
|
||||||
<div>
|
<div>
|
||||||
<input type="text" [(ngModel)]="settings.port" class="form-control form-control-custom " id="portNumber" name="Port" placeholder="Port Number" value="{{settings.port}}">
|
<input type="text" class="form-control form-control-custom " id="host" name="host" placeholder="localhost" formControlName="host">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="sender" class="control-label">Email Sender</label>
|
<label for="portNumber" class="control-label">SMTP Port</label>
|
||||||
<div>
|
<div>
|
||||||
<input type="text" class="form-control form-control-custom " id="sender" name="sender" [(ngModel)]="settings.sender" value="{{settings.sender}}" tooltipPosition="top" pTooltip="The email address that the emails will be sent from">
|
<input type="text" class="form-control form-control-custom " id="portNumber" name="Port" placeholder="Port Number" formControlName="port">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="adminEmail" class="control-label">Admin Email</label>
|
<label for="sender" class="control-label">Email Sender</label>
|
||||||
<div>
|
<div>
|
||||||
<input type="text" class="form-control form-control-custom " id="adminEmail" name="adminEmail" [(ngModel)]="settings.adminEmail" value="{{settings.adminEmail}}" tooltipPosition="top" pTooltip="The administrator email will be used to send emails for admin only notifications (e.g. New Requests that require approvals)">
|
<input type="text" class="form-control form-control-custom " id="sender" name="sender" formControlName="sender" tooltipPosition="top" pTooltip="The email address that the emails will be sent from">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
<div class="form-group" *ngIf="settings.authentication">
|
<label for="adminEmail" class="control-label">Admin Email</label>
|
||||||
<label for="username" class="control-label">Username</label>
|
<div>
|
||||||
<div>
|
<input type="text" class="form-control form-control-custom " id="adminEmail" name="adminEmail" formControlName="adminEmail" tooltipPosition="top" pTooltip="The administrator email will be used to send emails for admin only notifications (e.g. New Requests that require approvals)">
|
||||||
<input type="text" class="form-control form-control-custom " id="username" name="username" [(ngModel)]="settings.username" value="{{settings.username}}" pTooltip="The username if authentication is enabled" tooltipPosition="top">
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group" *ngIf="settings.authentication">
|
|
||||||
<label for="password" class="control-label">Password</label>
|
<div class="form-group" *ngIf="emailForm.controls['username'].validator">
|
||||||
<div>
|
<label for="username" class="control-label">Username</label>
|
||||||
<input type="password" class="form-control form-control-custom " id="password" name="password" [(ngModel)]="settings.password" value="{{settings.password}}" pTooltip="The password if authentication is enabled" tooltipPosition="top">
|
<div>
|
||||||
|
<input type="text" class="form-control form-control-custom " id="username" name="username" formControlName="username" pTooltip="The username if authentication is enabled" tooltipPosition="top">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group" *ngIf="emailForm.get('password').validator">
|
||||||
<div>
|
<label for="password" class="control-label">Password</label>
|
||||||
<button id="testPlex" type="submit" (click)="test()" class="btn btn-primary-outline">Test Connectivity <div id="spinner"></div></button>
|
<div>
|
||||||
|
<input type="password" class="form-control form-control-custom " id="password" name="password" formControlName="password" pTooltip="The password if authentication is enabled" tooltipPosition="top">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
<div class="form-group">
|
<button id="testPlex" type="submit" (click)="test()" class="btn btn-primary-outline">
|
||||||
<div>
|
Test Connectivity
|
||||||
<button (click)="save()" type="submit" id="save" class="btn btn-primary-outline">Submit</button>
|
<div id="spinner"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
|
<button [disabled]="emailForm.invalid" type="submit" id="save" class="btn btn-primary-outline">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<notification-templates [templates]="settings.notificationTemplates"></notification-templates>
|
<notification-templates [templates]="templates"></notification-templates>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
|
@ -1,34 +1,87 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { FormGroup, Validators, FormBuilder } from '@angular/forms';
|
||||||
|
|
||||||
import { IEmailNotificationSettings, NotificationType } from '../../interfaces/INotifcationSettings';
|
import { INotificationTemplates, IEmailNotificationSettings, NotificationType } from '../../interfaces/INotifcationSettings';
|
||||||
import { SettingsService } from '../../services/settings.service';
|
import { SettingsService } from '../../services/settings.service';
|
||||||
import { NotificationService } from "../../services/notification.service";
|
import { NotificationService } from "../../services/notification.service";
|
||||||
|
import { ValidationService } from "../../services/helpers/validation.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './emailnotification.component.html',
|
templateUrl: './emailnotification.component.html',
|
||||||
})
|
})
|
||||||
export class EmailNotificationComponent implements OnInit {
|
export class EmailNotificationComponent implements OnInit {
|
||||||
|
constructor(private settingsService: SettingsService,
|
||||||
|
private notificationService: NotificationService,
|
||||||
|
private fb: FormBuilder,
|
||||||
|
private validationService: ValidationService) { }
|
||||||
|
|
||||||
constructor(private settingsService: SettingsService, private notificationService: NotificationService) { }
|
|
||||||
|
|
||||||
settings: IEmailNotificationSettings;
|
|
||||||
NotificationType = NotificationType;
|
NotificationType = NotificationType;
|
||||||
|
templates: INotificationTemplates[];
|
||||||
|
|
||||||
|
emailForm: FormGroup;
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.settingsService.getEmailNotificationSettings().subscribe(x => this.settings = x);
|
this.settingsService.getEmailNotificationSettings().subscribe(x => {
|
||||||
|
this.templates = x.notificationTemplates;
|
||||||
|
|
||||||
|
this.emailForm = this.fb.group({
|
||||||
|
enabled: [x.enabled],
|
||||||
|
authentication: [x.authentication],
|
||||||
|
host: [x.host, [Validators.required]],
|
||||||
|
password: [x.password],
|
||||||
|
port: [x.port, [Validators.required]],
|
||||||
|
sender: [x.sender, [Validators.required, Validators.email]],
|
||||||
|
username: [x.username],
|
||||||
|
adminEmail: [x.adminEmail, [Validators.required, Validators.email]],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (x.authentication) {
|
||||||
|
this.validationService.enableValidation(this.emailForm, 'username');
|
||||||
|
this.validationService.enableValidation(this.emailForm, 'password');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.subscribeToAuthChanges();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
test() {
|
onSubmit(form: FormGroup) {
|
||||||
// TODO Emby Service
|
console.log(form.value, form.valid);
|
||||||
}
|
|
||||||
|
|
||||||
save() {
|
if (form.invalid) {
|
||||||
this.settingsService.saveEmailNotificationSettings(this.settings).subscribe(x => {
|
this.notificationService.error("Validation", "Please check your entered values");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var settings = <IEmailNotificationSettings>form.value;
|
||||||
|
settings.notificationTemplates = this.templates;
|
||||||
|
|
||||||
|
this.settingsService.saveEmailNotificationSettings(settings).subscribe(x => {
|
||||||
if (x) {
|
if (x) {
|
||||||
this.notificationService.success("Settings Saved", "Successfully saved Email settings");
|
this.notificationService.success("Settings Saved", "Successfully saved Email settings");
|
||||||
} else {
|
} else {
|
||||||
this.notificationService.success("Settings Saved", "There was an error when saving the Email settings");
|
this.notificationService.success("Settings Saved", "There was an error when saving the Email settings");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private subscribeToAuthChanges() {
|
||||||
|
const authCtrl = this.emailForm.controls.authentication;
|
||||||
|
const changes$ = authCtrl.valueChanges;
|
||||||
|
|
||||||
|
changes$.subscribe((auth: boolean) => {
|
||||||
|
|
||||||
|
if (auth) {
|
||||||
|
this.validationService.enableValidation(this.emailForm, 'username');
|
||||||
|
this.validationService.enableValidation(this.emailForm, 'password');
|
||||||
|
} else {
|
||||||
|
this.validationService.disableValidation(this.emailForm, 'username');
|
||||||
|
this.validationService.disableValidation(this.emailForm, 'password');
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,18 +1,27 @@
|
||||||
|
<i class="fa fa-info-circle" tooltipPosition="top" [escape]="false" pTooltip="{{helpText}}"></i>
|
||||||
|
|
||||||
|
|
||||||
<ngb-accordion [closeOthers]="true" activeIds="0-header">
|
<ngb-accordion [closeOthers]="true" activeIds="0-header">
|
||||||
<ngb-panel *ngFor="let template of templates" id="{{template.notificationType}}" title="{{NotificationType[template.notificationType] | humanize}}">
|
<ngb-panel *ngFor="let template of templates" id="{{template.notificationType}}" title="{{NotificationType[template.notificationType] | humanize}}">
|
||||||
<ng-template ngbPanelContent>
|
<ng-template ngbPanelContent>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password" class="control-label">Subject</label>
|
<div class="checkbox">
|
||||||
|
<input type="checkbox" id="enabled" [(ngModel)]="template.enabled" ng-checked="template.enabled"><label for="enabled">Enable</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label">Subject</label>
|
||||||
<div>
|
<div>
|
||||||
<input type="text" class="form-control form-control-custom" [(ngModel)]="template.subject" value="{{template.subject}}">
|
<input type="text" class="form-control form-control-custom" [(ngModel)]="template.subject" value="{{template.subject}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password" class="control-label">Message</label>
|
<label class="control-label">Message</label>
|
||||||
<div>
|
<div>
|
||||||
<textarea type="text" class="form-control form-control-custom" [(ngModel)]="template.message" value="{{template.message}}"></textarea>
|
<textarea type="text" class="form-control form-control-custom" [(ngModel)]="template.message" value="{{template.message}}"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,4 +9,16 @@ import { INotificationTemplates, NotificationType } from '../../interfaces/INoti
|
||||||
export class NotificationTemplate {
|
export class NotificationTemplate {
|
||||||
@Input() templates: INotificationTemplates[];
|
@Input() templates: INotificationTemplates[];
|
||||||
NotificationType = NotificationType;
|
NotificationType = NotificationType;
|
||||||
|
|
||||||
|
helpText = `
|
||||||
|
{RequestedUser} : The User who requested the content <br/>
|
||||||
|
{RequestedDate} : The Date the media was requested <br/>
|
||||||
|
{Title} : The title of the request e.g. Lion King <br/>
|
||||||
|
{Type} : The request type e.g. Movie/Tv Show <br/>
|
||||||
|
{LongDate} : 15 June 2017 <br/>
|
||||||
|
{ShortDate} : 15/06/2017 <br/>
|
||||||
|
{LongTime} : 16:02:34 <br/>
|
||||||
|
{ShortTime} : 16:02 <br/>
|
||||||
|
|
||||||
|
`
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { NgModule, } from '@angular/core';
|
import { NgModule, } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
import { NgbModule, NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModule, NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap';
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import { AuthGuard } from '../auth/auth.guard';
|
||||||
import { AuthModule } from '../auth/auth.module';
|
import { AuthModule } from '../auth/auth.module';
|
||||||
import { SonarrService } from '../services/applications/sonarr.service';
|
import { SonarrService } from '../services/applications/sonarr.service';
|
||||||
import { RadarrService } from '../services/applications/radarr.service';
|
import { RadarrService } from '../services/applications/radarr.service';
|
||||||
|
import { ValidationService } from '../services/helpers/validation.service';
|
||||||
|
|
||||||
import { OmbiComponent } from './ombi/ombi.component';
|
import { OmbiComponent } from './ombi/ombi.component';
|
||||||
import { PlexComponent } from './plex/plex.component';
|
import { PlexComponent } from './plex/plex.component';
|
||||||
|
@ -23,7 +24,7 @@ import { NotificationTemplate } from './notifications/notificationtemplate.compo
|
||||||
import { SettingsMenuComponent } from './settingsmenu.component';
|
import { SettingsMenuComponent } from './settingsmenu.component';
|
||||||
import { HumanizePipe } from '../pipes/HumanizePipe';
|
import { HumanizePipe } from '../pipes/HumanizePipe';
|
||||||
|
|
||||||
import { MenuModule, InputSwitchModule, InputTextModule, TooltipModule } from 'primeng/primeng';
|
import { MenuModule, InputSwitchModule, InputTextModule, TooltipModule, AutoCompleteModule } from 'primeng/primeng';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: 'Settings/Ombi', component: OmbiComponent, canActivate: [AuthGuard] },
|
{ path: 'Settings/Ombi', component: OmbiComponent, canActivate: [AuthGuard] },
|
||||||
|
@ -40,6 +41,7 @@ const routes: Routes = [
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
RouterModule.forChild(routes),
|
RouterModule.forChild(routes),
|
||||||
MenuModule,
|
MenuModule,
|
||||||
InputSwitchModule,
|
InputSwitchModule,
|
||||||
|
@ -47,7 +49,8 @@ const routes: Routes = [
|
||||||
AuthModule,
|
AuthModule,
|
||||||
NgbModule,
|
NgbModule,
|
||||||
TooltipModule,
|
TooltipModule,
|
||||||
NgbAccordionModule
|
NgbAccordionModule,
|
||||||
|
AutoCompleteModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
SettingsMenuComponent,
|
SettingsMenuComponent,
|
||||||
|
@ -70,6 +73,7 @@ const routes: Routes = [
|
||||||
AuthService,
|
AuthService,
|
||||||
RadarrService,
|
RadarrService,
|
||||||
AuthGuard,
|
AuthGuard,
|
||||||
|
ValidationService
|
||||||
],
|
],
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,6 +9,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Models;
|
using Ombi.Models;
|
||||||
|
using Ombi.Notifications.Models;
|
||||||
|
|
||||||
namespace Ombi.Controllers
|
namespace Ombi.Controllers
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue