Browse Source

Added background services application.

pull/29/head
Halil İbrahim Kalkan 6 years ago
parent
commit
f00dfbfac9
  1. 7
      EventHub.sln
  2. 5
      src/EventHub.Application/EventHub.Application.csproj
  3. 23
      src/EventHub.Application/EventHubApplicationModule.cs
  4. 34
      src/EventHub.BackgroundServices/EventHub.BackgroundServices.csproj
  5. 36
      src/EventHub.BackgroundServices/EventHubBackgroundServicesHostedService.cs
  6. 32
      src/EventHub.BackgroundServices/EventHubBackgroundServicesModule.cs
  7. 0
      src/EventHub.BackgroundServices/Events/EventReminderNotifier.cs
  8. 0
      src/EventHub.BackgroundServices/Events/EventReminderWorker.cs
  9. 161
      src/EventHub.BackgroundServices/Events/EventTimingChangeNotifier.cs
  10. 100
      src/EventHub.BackgroundServices/Events/EventTimingChangeWorker.cs
  11. 23
      src/EventHub.BackgroundServices/Events/NewEventDetectorWorker.cs
  12. 34
      src/EventHub.BackgroundServices/Events/NewEventNotifier.cs
  13. 53
      src/EventHub.BackgroundServices/Program.cs
  14. 3
      src/EventHub.BackgroundServices/appsettings.json
  15. 0
      src/EventHub.Domain/Emailing/EmailTemplateDefinitionProvider.cs
  16. 0
      src/EventHub.Domain/Emailing/EmailTemplates.cs
  17. 0
      src/EventHub.Domain/Emailing/Templates/EventRegistration.tpl
  18. 0
      src/EventHub.Domain/Emailing/Templates/EventReminder.tpl
  19. 312
      src/EventHub.Domain/Emailing/Templates/EventTimingChanged.tpl
  20. 0
      src/EventHub.Domain/Emailing/Templates/NewEventCreated.tpl
  21. 10
      src/EventHub.Domain/EventHub.Domain.csproj
  22. 6
      src/EventHub.Domain/EventHubDomainModule.cs

7
EventHub.sln

@ -41,6 +41,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventHub.Web.Admin", "src\E
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventHub.Web", "src\EventHub.Web\EventHub.Web.csproj", "{19F3FAD2-740F-4933-A394-4B030E2ABE6A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventHub.BackgroundServices", "src\EventHub.BackgroundServices\EventHub.BackgroundServices.csproj", "{7A16923F-06FA-40B4-8A54-69E7828B1D69}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -115,6 +117,10 @@ Global
{19F3FAD2-740F-4933-A394-4B030E2ABE6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19F3FAD2-740F-4933-A394-4B030E2ABE6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19F3FAD2-740F-4933-A394-4B030E2ABE6A}.Release|Any CPU.Build.0 = Release|Any CPU
{7A16923F-06FA-40B4-8A54-69E7828B1D69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7A16923F-06FA-40B4-8A54-69E7828B1D69}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7A16923F-06FA-40B4-8A54-69E7828B1D69}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7A16923F-06FA-40B4-8A54-69E7828B1D69}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -137,6 +143,7 @@ Global
{AA94D832-1CCC-4715-95A9-A483F23A1A5D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
{27B2DDC7-8B75-4322-A312-25419C15D9D8} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
{19F3FAD2-740F-4933-A394-4B030E2ABE6A} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
{7A16923F-06FA-40B4-8A54-69E7828B1D69} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6AAFA1C6-603E-13FA-45E5-7910AA9F661D}

5
src/EventHub.Application/EventHub.Application.csproj

@ -18,9 +18,4 @@
<PackageReference Include="Volo.Abp.PermissionManagement.Application" Version="4.2.1" />
</ItemGroup>
<ItemGroup>
<None Remove="Emailing\Templates\*.tpl" />
<EmbeddedResource Include="Emailing\Templates\*.tpl" />
</ItemGroup>
</Project>

23
src/EventHub.Application/EventHubApplicationModule.cs

@ -1,12 +1,8 @@
using EventHub.Events;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account;
using Volo.Abp.AutoMapper;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Identity;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement;
using Volo.Abp.VirtualFileSystem;
namespace EventHub
{
@ -15,29 +11,16 @@ namespace EventHub
typeof(AbpAccountApplicationModule),
typeof(EventHubApplicationContractsModule),
typeof(AbpIdentityApplicationModule),
typeof(AbpPermissionManagementApplicationModule),
typeof(AbpBackgroundWorkersModule)
)]
typeof(AbpPermissionManagementApplicationModule)
)]
public class EventHubApplicationModule : AbpModule
{
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
context.AddBackgroundWorker<EventReminderWorker>();
context.AddBackgroundWorker<NewEventDetectorWorker>();
context.AddBackgroundWorker<EventTimingChangeWorker>();
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<EventHubApplicationModule>();
});
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<EventHubApplicationModule>("EventHub");
});
}
}
}

34
src/EventHub.BackgroundServices/EventHub.BackgroundServices.csproj

@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>EventHub</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Autofac" Version="4.2.1" />
<PackageReference Include="Volo.Abp.BackgroundWorkers" Version="4.2.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.*" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
</ItemGroup>
<ItemGroup>
<Content Include="appsettings.json">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EventHub.Domain\EventHub.Domain.csproj" />
</ItemGroup>
</Project>

36
src/EventHub.BackgroundServices/EventHubBackgroundServicesHostedService.cs

@ -0,0 +1,36 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Volo.Abp;
namespace EventHub
{
public class EventHubBackgroundServicesHostedService : IHostedService
{
private readonly IAbpApplicationWithExternalServiceProvider _application;
private readonly IServiceProvider _serviceProvider;
public EventHubBackgroundServicesHostedService(
IAbpApplicationWithExternalServiceProvider application,
IServiceProvider serviceProvider)
{
_application = application;
_serviceProvider = serviceProvider;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_application.Initialize(_serviceProvider);
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_application.Shutdown();
return Task.CompletedTask;
}
}
}

32
src/EventHub.BackgroundServices/EventHubBackgroundServicesModule.cs

@ -0,0 +1,32 @@
using EventHub.Events;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Volo.Abp;
using Volo.Abp.Autofac;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Modularity;
namespace EventHub
{
[DependsOn(
typeof(AbpAutofacModule)
)]
public class EventHubBackgroundServicesModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var hostEnvironment = context.Services.GetSingletonInstance<IHostEnvironment>();
context.Services.AddHostedService<EventHubBackgroundServicesHostedService>();
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
context.AddBackgroundWorker<EventReminderWorker>();
context.AddBackgroundWorker<NewEventDetectorWorker>();
context.AddBackgroundWorker<EventTimingChangeWorker>();
}
}
}

0
src/EventHub.Application/Events/EventReminderNotifier.cs → src/EventHub.BackgroundServices/Events/EventReminderNotifier.cs

0
src/EventHub.Application/Events/EventReminderWorker.cs → src/EventHub.BackgroundServices/Events/EventReminderWorker.cs

161
src/EventHub.Application/Events/EventTimingChangeNotifier.cs → src/EventHub.BackgroundServices/Events/EventTimingChangeNotifier.cs

@ -1,82 +1,81 @@
using System;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using EventHub.Emailing;
using EventHub.Events.Registrations;
using EventHub.Users;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Emailing;
using Volo.Abp.Linq;
using Volo.Abp.TextTemplating;
namespace EventHub.Events
{
public class EventTimingChangeNotifier : ITransientDependency
{
private readonly IEmailSender _emailSender;
private readonly ITemplateRenderer _templateRenderer;
private readonly IRepository<EventRegistration, Guid> _eventRegistrationRepository;
private readonly IAsyncQueryableExecuter _asyncExecuter;
private readonly IRepository<AppUser, Guid> _userRepository;
public EventTimingChangeNotifier(
IEmailSender emailSender,
ITemplateRenderer templateRenderer,
IRepository<EventRegistration, Guid> eventRegistrationRepository,
IAsyncQueryableExecuter asyncExecuter,
IRepository<AppUser, Guid> userRepository
)
{
_emailSender = emailSender;
_templateRenderer = templateRenderer;
_eventRegistrationRepository = eventRegistrationRepository;
_asyncExecuter = asyncExecuter;
_userRepository = userRepository;
}
public async Task NotifyAsync(Event @event)
{
if (@event is null)
{
return;
}
var eventRegistrationQueryable = await _eventRegistrationRepository.GetQueryableAsync();
var query = eventRegistrationQueryable
.Where(x => x.EventId == @event.Id && !x.IsTimingChangeEmailSent);
var eventRegistrations = await _asyncExecuter.ToListAsync(query);
foreach (var eventRegistration in eventRegistrations)
{
var user = await _userRepository.FindAsync(eventRegistration.UserId);
if (user is null)
{
continue;
}
var model = new
{
UserName = user.GetFullNameOrUsername(),
Title = @event.Title,
StartTime = @event.StartTime,
EndTime = @event.EndTime,
Url = @event.Url
};
await _emailSender.QueueAsync(
user.Email,
"Event time has been changed!",
await _templateRenderer.RenderAsync(EmailTemplates.EventTimingChanged, model)
);
eventRegistration.IsTimingChangeEmailSent = true;
}
await _eventRegistrationRepository.UpdateManyAsync(eventRegistrations, autoSave: true);
}
}
using System;
using System.Linq;
using System.Threading.Tasks;
using EventHub.Emailing;
using EventHub.Events.Registrations;
using EventHub.Users;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Emailing;
using Volo.Abp.Linq;
using Volo.Abp.TextTemplating;
namespace EventHub.Events
{
public class EventTimingChangeNotifier : ITransientDependency
{
private readonly IEmailSender _emailSender;
private readonly ITemplateRenderer _templateRenderer;
private readonly IRepository<EventRegistration, Guid> _eventRegistrationRepository;
private readonly IAsyncQueryableExecuter _asyncExecuter;
private readonly IRepository<AppUser, Guid> _userRepository;
public EventTimingChangeNotifier(
IEmailSender emailSender,
ITemplateRenderer templateRenderer,
IRepository<EventRegistration, Guid> eventRegistrationRepository,
IAsyncQueryableExecuter asyncExecuter,
IRepository<AppUser, Guid> userRepository
)
{
_emailSender = emailSender;
_templateRenderer = templateRenderer;
_eventRegistrationRepository = eventRegistrationRepository;
_asyncExecuter = asyncExecuter;
_userRepository = userRepository;
}
public async Task NotifyAsync(Event @event)
{
if (@event is null)
{
return;
}
var eventRegistrationQueryable = await _eventRegistrationRepository.GetQueryableAsync();
var query = eventRegistrationQueryable
.Where(x => x.EventId == @event.Id && !x.IsTimingChangeEmailSent);
var eventRegistrations = await _asyncExecuter.ToListAsync(query);
foreach (var eventRegistration in eventRegistrations)
{
var user = await _userRepository.FindAsync(eventRegistration.UserId);
if (user is null)
{
continue;
}
var model = new
{
UserName = user.GetFullNameOrUsername(),
Title = @event.Title,
StartTime = @event.StartTime,
EndTime = @event.EndTime,
Url = @event.Url
};
await _emailSender.QueueAsync(
user.Email,
"Event time has been changed!",
await _templateRenderer.RenderAsync(EmailTemplates.EventTimingChanged, model)
);
eventRegistration.IsTimingChangeEmailSent = true;
}
await _eventRegistrationRepository.UpdateManyAsync(eventRegistrations, autoSave: true);
}
}
}

100
src/EventHub.Application/Events/EventTimingChangeWorker.cs → src/EventHub.BackgroundServices/Events/EventTimingChangeWorker.cs

@ -1,51 +1,51 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using EventHub.Events.Registrations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq;
using Volo.Abp.Threading;
using Volo.Abp.Uow;
namespace EventHub.Events
{
public class EventTimingChangeWorker : AsyncPeriodicBackgroundWorkerBase
{
public EventTimingChangeWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory) : base(timer, serviceScopeFactory)
{
Timer.Period = 60000; //1 minute
}
[UnitOfWork(isTransactional: false)]
protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
{
var eventTimingChangeNotifier = workerContext.ServiceProvider.GetRequiredService<EventTimingChangeNotifier>();
var eventRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<Event, Guid>>();
var eventRegistrationRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<EventRegistration, Guid>>();
var asyncExecuter = workerContext.ServiceProvider.GetRequiredService<IAsyncQueryableExecuter>();
var eventRegistrationQueryable = await eventRegistrationRepository.GetQueryableAsync();
var query = eventRegistrationQueryable
.Where(x => !x.IsTimingChangeEmailSent)
.Select(x => x.EventId)
.Distinct();
var eventRegistrations = await asyncExecuter.ToListAsync(query);
foreach (var eventRegistration in eventRegistrations)
{
try
{
await eventTimingChangeNotifier.NotifyAsync(await eventRepository.FindAsync(eventRegistration));
}
catch (Exception e)
{
Logger.LogError($"An error occurred while sending an email to the attendees of the event after the event time has changed. Error message: {e.Message}");
}
}
}
}
using System;
using System.Linq;
using System.Threading.Tasks;
using EventHub.Events.Registrations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq;
using Volo.Abp.Threading;
using Volo.Abp.Uow;
namespace EventHub.Events
{
public class EventTimingChangeWorker : AsyncPeriodicBackgroundWorkerBase
{
public EventTimingChangeWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory) : base(timer, serviceScopeFactory)
{
Timer.Period = 60000; //1 minute
}
[UnitOfWork(isTransactional: false)]
protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
{
var eventTimingChangeNotifier = workerContext.ServiceProvider.GetRequiredService<EventTimingChangeNotifier>();
var eventRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<Event, Guid>>();
var eventRegistrationRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<EventRegistration, Guid>>();
var asyncExecuter = workerContext.ServiceProvider.GetRequiredService<IAsyncQueryableExecuter>();
var eventRegistrationQueryable = await eventRegistrationRepository.GetQueryableAsync();
var query = eventRegistrationQueryable
.Where(x => !x.IsTimingChangeEmailSent)
.Select(x => x.EventId)
.Distinct();
var eventRegistrations = await asyncExecuter.ToListAsync(query);
foreach (var eventRegistration in eventRegistrations)
{
try
{
await eventTimingChangeNotifier.NotifyAsync(await eventRepository.FindAsync(eventRegistration));
}
catch (Exception e)
{
Logger.LogError($"An error occurred while sending an email to the attendees of the event after the event time has changed. Error message: {e.Message}");
}
}
}
}
}

23
src/EventHub.Application/Events/NewEventDetectorWorker.cs → src/EventHub.BackgroundServices/Events/NewEventDetectorWorker.cs

@ -13,8 +13,12 @@ namespace EventHub.Events
{
public class NewEventDetectorWorker : AsyncPeriodicBackgroundWorkerBase
{
public NewEventDetectorWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory)
: base(timer, serviceScopeFactory)
public NewEventDetectorWorker(
AbpAsyncTimer timer,
IServiceScopeFactory serviceScopeFactory)
: base(
timer,
serviceScopeFactory)
{
Timer.Period = 60_000;
}
@ -26,23 +30,22 @@ namespace EventHub.Events
var eventRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<Event, Guid>>();
var asyncExecuter = workerContext.ServiceProvider.GetRequiredService<IAsyncQueryableExecuter>();
var eventQueryable = await eventRepository.GetQueryableAsync();
var eventQuery = eventQueryable.Where(x => x.IsEmailSentToMembers == false);
var queryable = await eventRepository.GetQueryableAsync();
var newEvents = await asyncExecuter.ToListAsync(
queryable.Where(x => x.IsEmailSentToMembers == false)
);
var newEvents = await asyncExecuter.ToListAsync(eventQuery);
foreach (var @event in newEvents)
{
try
{
await newEventNotifier.NotifyAsync(@event);
@event.IsEmailSentToMembers = true;
await eventRepository.UpdateAsync(@event);
}
catch (Exception e)
catch (Exception ex)
{
@event.IsEmailSentToMembers = false;
Logger.LogError($"An error occurred while sending an email to the members of the organization after the new event was created. Error message: {e.Message}");
Logger.LogException(ex);
}
}
}

34
src/EventHub.Application/Events/NewEventNotifier.cs → src/EventHub.BackgroundServices/Events/NewEventNotifier.cs

@ -16,15 +16,15 @@ namespace EventHub.Events
{
private readonly IEmailSender _emailSender;
private readonly ITemplateRenderer _templateRenderer;
private readonly IRepository<OrganizationMembership, Guid> _organizationMembershipsRepository;
private readonly IRepository<OrganizationMembership, Guid> _organizationMembershipsRepository;
private readonly IRepository<AppUser, Guid> _userRepository;
private readonly IAsyncQueryableExecuter _asyncExecuter;
public NewEventNotifier(
IEmailSender emailSender,
IEmailSender emailSender,
ITemplateRenderer templateRenderer,
IRepository<OrganizationMembership, Guid> organizationMembershipsRepository,
IRepository<AppUser, Guid> userRepository,
IRepository<OrganizationMembership, Guid> organizationMembershipsRepository,
IRepository<AppUser, Guid> userRepository,
IAsyncQueryableExecuter asyncExecuter)
{
_emailSender = emailSender;
@ -33,31 +33,23 @@ namespace EventHub.Events
_userRepository = userRepository;
_asyncExecuter = asyncExecuter;
}
public async Task NotifyAsync(Event @event)
{
if (@event is null)
{
return;
}
var organizationMembershipsQueryable = await _organizationMembershipsRepository.GetQueryableAsync();
var membershipQuery = organizationMembershipsQueryable
.Where(x => x.OrganizationId == @event.OrganizationId);
var organizationMembers = await _asyncExecuter.ToListAsync(membershipQuery);
var queryable = await _organizationMembershipsRepository.GetQueryableAsync();
var organizationMembers = await _asyncExecuter.ToListAsync(
queryable.Where(x => x.OrganizationId == @event.OrganizationId)
);
foreach (var member in organizationMembers)
{
var user = await _userRepository.FindAsync(member.UserId);
if (user is null)
{
continue;
}
var model = new
var templateModel = new
{
UserName = user.GetFullNameOrUsername(),
Title = @event.Title,
@ -65,12 +57,12 @@ namespace EventHub.Events
EndTime = @event.EndTime,
Url = @event.Url
};
await _emailSender.QueueAsync(
user.Email,
$"Do you attend the {@event.Title} event?",
await _templateRenderer.RenderAsync(EmailTemplates.NewEventCreated, model)
);
await _templateRenderer.RenderAsync(EmailTemplates.NewEventCreated, templateModel)
);
}
}
}

53
src/EventHub.BackgroundServices/Program.cs

@ -0,0 +1,53 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
namespace EventHub
{
public class Program
{
public static async Task<int> Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
#if DEBUG
.MinimumLevel.Debug()
#else
.MinimumLevel.Information()
#endif
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Async(c => c.File("Logs/logs.txt"))
.WriteTo.Async(c => c.Console())
.CreateLogger();
try
{
Log.Information("Starting console host.");
await CreateHostBuilder(args).RunConsoleAsync();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly!");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
internal static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseAutofac()
.UseSerilog()
.ConfigureServices((hostContext, services) =>
{
services.AddApplication<EventHubBackgroundServicesModule>();
});
}
}

3
src/EventHub.BackgroundServices/appsettings.json

@ -0,0 +1,3 @@
{
}

0
src/EventHub.Application/Emailing/EmailTemplateDefinitionProvider.cs → src/EventHub.Domain/Emailing/EmailTemplateDefinitionProvider.cs

0
src/EventHub.Application/Emailing/EmailTemplates.cs → src/EventHub.Domain/Emailing/EmailTemplates.cs

0
src/EventHub.Application/Emailing/Templates/EventRegistration.tpl → src/EventHub.Domain/Emailing/Templates/EventRegistration.tpl

0
src/EventHub.Application/Emailing/Templates/EventReminder.tpl → src/EventHub.Domain/Emailing/Templates/EventReminder.tpl

312
src/EventHub.Application/Emailing/Templates/EventTimingChanged.tpl → src/EventHub.Domain/Emailing/Templates/EventTimingChanged.tpl

@ -1,157 +1,157 @@
<html>
<head>
<meta name="viewport" content="width=device-width">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Eventhub</title>
<style>
@media only screen and (max-width: 620px) {
table[class=mail-body] h1{
font-size: 36px !important;
margin-bottom: 10px !important;
}
table[class=mail-body] .content {
padding: 0 !important;
}
table[class=mail-body] .container {
padding: 0 !important;
width: 100% !important;
}
table[class=mail-body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
table[class=mail-body] td {
width: 100% !important;
float: left!important;
}
table[class=mail-body] td a.btn {
display: block !important;
text-align: center;
}
table[class=mail-body] td h2 {
margin: 10px 0 !important;
}
table[class=mail-body] td .cont {
padding: 30px !important;
}
}
</style>
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0" class="mail-body" style="background-color: #ffffff;width: 100%; font-size: 16px;line-height: 1.4;font-family: Arial, sans-serif;">
<tbody>
<tr>
<td class="container" width="800" style="display: block;margin: 0 auto !important; max-width: 800px;padding: 10px;width: 800px;">
<div class="content" style="box-sizing: border-box;display: block;margin: 0 auto;max-width: 800px;padding: 0px;">
<div style="display: flex; padding-top: 1.5rem">
<h1 style="justify-content: center;margin-left: auto;margin-right: auto;align-content: center;">EventHub</h1>
</div>
<!-- START CENTERED WHITE CONTAINER -->
<div style="display: flex;">
<h1 style="justify-content: center;margin-left: auto;margin-right: auto;align-content: center;">{{model.title}} event time has been changed!</h1>
</div>
<table class="main" style="background: #ffffff;border-radius: 3px; width: 100%;">
<!-- START MAIN CONTENT AREA -->
<tbody>
<tr>
<td class="wrapper" width="800">
<table class="main" style="background: #ffffff;border-radius: 3px;width: 100%;">
<tbody>
<tr>
<td class="wrapper" width="800">
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%; ">
<tbody>
<tr>
<td style="vertical-align: top;" width="100%">
<div class="cont" style="background: #eeeeee; border-radius: 10px; padding: 40px; margin-top: 20px;">
<table style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%; ">
<tbody>
<tr>
<td width="100%" style="vertical-align: top; font-size: 16px; font-family: Arial, sans-serif; color: #444; margin-top: 20px; margin-bottom: 20px; line-height: 1.75">
<p>
Hi {{model.user_name}},
</p>
<p>
The "{{model.title}}" event time just rescheduled.
</p>
<div>
<table border="0" cellpadding="0" cellspacing="0" style=" border-collapse: separate; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
<tbody>
<tr style="text-align: center">
<td style="vertical-align: top;">
<p style="font-size: 13px; font-family: Arial, sans-serif; color: #777777; margin: 0; margin-top: 30px;">Start Time</p>
<p style="font-size: 21px; font-family: Arial, sans-serif; color: #444444; margin-bottom: 30px; margin-top: 6px;">{{model.start_time}}</p>
</td>
<td style="vertical-align: top;">
<p style="font-size: 13px; font-family: Arial, sans-serif; color: #777777; margin: 0; margin-top: 30px;">End Time</p>
<p style="font-size: 21px; font-family: Arial, sans-serif; color: #444444; margin-bottom: 30px; margin-top: 6px;">{{model.end_time}}</p>
</td>
</tr>
</tbody>
</table>
<p style="margin-bottom: 20px; margin-top: 20px; text-align: center;">
<a href="/events/{{model.url}}" class="btn" target="_blank" style="padding: 15px; background: #e90052; border-radius: 40px; text-align: center; color: white; font-weight: bold; text-decoration: none; font-size: 18px; padding-left: 45px; padding-right: 45px;">Event Details</a>
</p>
</div>
<p style="font-size: 16px; font-family: Arial, sans-serif; color: #444; margin-top: 20px; margin-bottom: 0px;">
Thank you,<br> EventHub
</p>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<!-- START FOOTER -->
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;">
<tbody>
<tr>
<td class="content-block" style="vertical-align: top;" width="800">
<div class="cont" style="background: #ffffff;border-top: 2px solid #eee; padding: 35px 40px 5px; margin-top: 0px; text-align: center;">
<a href="https://eventhub.abp.io/" style="font-size: 16px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; text-decoration: none;">Home</a>
</div>
</td>
</tr>
<tr>
<td class="content-block powered-by" style="vertical-align: top;" width="100%">
<div class="cont" style="background: #ffffff; border-radius: 10px; padding: 5px 40px; margin-top: 10px; margin-bottom: 50px; text-align: center;">
<a href="mailto:info@eventhub.abp.io" style="font-size: 16px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; text-decoration: none;"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAARCAYAAADHeGwwAAABMElEQVQ4je3TvyvFYRQG8M+9LEwWiV0xyeAi2ZTUFQuZDAqTxUCJzY9BFotS/gAySAZFEgYlySzFLosfs169w6XL/V6uzbO973vO85z3OeekstlsGRYxrrTYw1g56jGNO6yivAQyS5hFdRpHGMQauvDwC+IXDGAGnTgJApXYxAJO0YLrH5Dfog3bmMAhatI5AUF1B4/oiIFJcYAMbrCRa3X6E0EvzlEbbZtLILCMHlQESzCS+/hZIKARF7Ef8+jDc564VwxhCq24jL/4gHwCAVXYxyR2o7e3Oe/30cbQuzEcB7/zEX03kkF8BU2RJFS3hVS07wnrGP2GI9HMD6MB/eiOd9Wx6vZCyUmXKhM9Hojn8JO6JInFbG2YrLMi4t/xVZNLhn+BgghNvkLzn7Bz9QbIADMmEt9imAAAAABJRU5ErkJggg==" width="16"> info@eventhub.abp.io</a>
<span style="font-size: 16px; font-family: Arial, sans-serif; color: #777; margin-right: 0px; text-decoration: none;"><strong>EventHub</strong> - Powered by Volosoft</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- END FOOTER -->
<!-- END CENTERED WHITE CONTAINER -->
</td>
</tr>
</tbody>
</table>
</body>
<html>
<head>
<meta name="viewport" content="width=device-width">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Eventhub</title>
<style>
@media only screen and (max-width: 620px) {
table[class=mail-body] h1{
font-size: 36px !important;
margin-bottom: 10px !important;
}
table[class=mail-body] .content {
padding: 0 !important;
}
table[class=mail-body] .container {
padding: 0 !important;
width: 100% !important;
}
table[class=mail-body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
table[class=mail-body] td {
width: 100% !important;
float: left!important;
}
table[class=mail-body] td a.btn {
display: block !important;
text-align: center;
}
table[class=mail-body] td h2 {
margin: 10px 0 !important;
}
table[class=mail-body] td .cont {
padding: 30px !important;
}
}
</style>
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0" class="mail-body" style="background-color: #ffffff;width: 100%; font-size: 16px;line-height: 1.4;font-family: Arial, sans-serif;">
<tbody>
<tr>
<td class="container" width="800" style="display: block;margin: 0 auto !important; max-width: 800px;padding: 10px;width: 800px;">
<div class="content" style="box-sizing: border-box;display: block;margin: 0 auto;max-width: 800px;padding: 0px;">
<div style="display: flex; padding-top: 1.5rem">
<h1 style="justify-content: center;margin-left: auto;margin-right: auto;align-content: center;">EventHub</h1>
</div>
<!-- START CENTERED WHITE CONTAINER -->
<div style="display: flex;">
<h1 style="justify-content: center;margin-left: auto;margin-right: auto;align-content: center;">{{model.title}} event time has been changed!</h1>
</div>
<table class="main" style="background: #ffffff;border-radius: 3px; width: 100%;">
<!-- START MAIN CONTENT AREA -->
<tbody>
<tr>
<td class="wrapper" width="800">
<table class="main" style="background: #ffffff;border-radius: 3px;width: 100%;">
<tbody>
<tr>
<td class="wrapper" width="800">
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%; ">
<tbody>
<tr>
<td style="vertical-align: top;" width="100%">
<div class="cont" style="background: #eeeeee; border-radius: 10px; padding: 40px; margin-top: 20px;">
<table style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%; ">
<tbody>
<tr>
<td width="100%" style="vertical-align: top; font-size: 16px; font-family: Arial, sans-serif; color: #444; margin-top: 20px; margin-bottom: 20px; line-height: 1.75">
<p>
Hi {{model.user_name}},
</p>
<p>
The "{{model.title}}" event time just rescheduled.
</p>
<div>
<table border="0" cellpadding="0" cellspacing="0" style=" border-collapse: separate; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
<tbody>
<tr style="text-align: center">
<td style="vertical-align: top;">
<p style="font-size: 13px; font-family: Arial, sans-serif; color: #777777; margin: 0; margin-top: 30px;">Start Time</p>
<p style="font-size: 21px; font-family: Arial, sans-serif; color: #444444; margin-bottom: 30px; margin-top: 6px;">{{model.start_time}}</p>
</td>
<td style="vertical-align: top;">
<p style="font-size: 13px; font-family: Arial, sans-serif; color: #777777; margin: 0; margin-top: 30px;">End Time</p>
<p style="font-size: 21px; font-family: Arial, sans-serif; color: #444444; margin-bottom: 30px; margin-top: 6px;">{{model.end_time}}</p>
</td>
</tr>
</tbody>
</table>
<p style="margin-bottom: 20px; margin-top: 20px; text-align: center;">
<a href="/events/{{model.url}}" class="btn" target="_blank" style="padding: 15px; background: #e90052; border-radius: 40px; text-align: center; color: white; font-weight: bold; text-decoration: none; font-size: 18px; padding-left: 45px; padding-right: 45px;">Event Details</a>
</p>
</div>
<p style="font-size: 16px; font-family: Arial, sans-serif; color: #444; margin-top: 20px; margin-bottom: 0px;">
Thank you,<br> EventHub
</p>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<!-- START FOOTER -->
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;">
<tbody>
<tr>
<td class="content-block" style="vertical-align: top;" width="800">
<div class="cont" style="background: #ffffff;border-top: 2px solid #eee; padding: 35px 40px 5px; margin-top: 0px; text-align: center;">
<a href="https://eventhub.abp.io/" style="font-size: 16px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; text-decoration: none;">Home</a>
</div>
</td>
</tr>
<tr>
<td class="content-block powered-by" style="vertical-align: top;" width="100%">
<div class="cont" style="background: #ffffff; border-radius: 10px; padding: 5px 40px; margin-top: 10px; margin-bottom: 50px; text-align: center;">
<a href="mailto:info@eventhub.abp.io" style="font-size: 16px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; text-decoration: none;"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAARCAYAAADHeGwwAAABMElEQVQ4je3TvyvFYRQG8M+9LEwWiV0xyeAi2ZTUFQuZDAqTxUCJzY9BFotS/gAySAZFEgYlySzFLosfs169w6XL/V6uzbO973vO85z3OeekstlsGRYxrrTYw1g56jGNO6yivAQyS5hFdRpHGMQauvDwC+IXDGAGnTgJApXYxAJO0YLrH5Dfog3bmMAhatI5AUF1B4/oiIFJcYAMbrCRa3X6E0EvzlEbbZtLILCMHlQESzCS+/hZIKARF7Ef8+jDc564VwxhCq24jL/4gHwCAVXYxyR2o7e3Oe/30cbQuzEcB7/zEX03kkF8BU2RJFS3hVS07wnrGP2GI9HMD6MB/eiOd9Wx6vZCyUmXKhM9Hojn8JO6JInFbG2YrLMi4t/xVZNLhn+BgghNvkLzn7Bz9QbIADMmEt9imAAAAABJRU5ErkJggg==" width="16"> info@eventhub.abp.io</a>
<span style="font-size: 16px; font-family: Arial, sans-serif; color: #777; margin-right: 0px; text-decoration: none;"><strong>EventHub</strong> - Powered by Volosoft</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- END FOOTER -->
<!-- END CENTERED WHITE CONTAINER -->
</td>
</tr>
</tbody>
</table>
</body>
</html>

0
src/EventHub.Application/Emailing/Templates/NewEventCreated.tpl → src/EventHub.Domain/Emailing/Templates/NewEventCreated.tpl

10
src/EventHub.Domain/EventHub.Domain.csproj

@ -5,6 +5,7 @@
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>EventHub</RootNamespace>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
</PropertyGroup>
<ItemGroup>
@ -23,4 +24,13 @@
<PackageReference Include="Volo.Abp.SettingManagement.Domain" Version="4.2.1" />
</ItemGroup>
<ItemGroup>
<None Remove="Emailing\Templates\*.tpl" />
<EmbeddedResource Include="Emailing\Templates\*.tpl" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="5.0.*" />
</ItemGroup>
</Project>

6
src/EventHub.Domain/EventHubDomainModule.cs

@ -10,6 +10,7 @@ using Volo.Abp.PermissionManagement.Identity;
using Volo.Abp.PermissionManagement.IdentityServer;
using Volo.Abp.SettingManagement;
using Volo.Abp.BlobStoring.Database;
using Volo.Abp.VirtualFileSystem;
namespace EventHub
{
@ -29,6 +30,11 @@ namespace EventHub
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<EventHubDomainModule>();
});
#if DEBUG
context.Services.Replace(ServiceDescriptor.Singleton<IEmailSender, NullEmailSender>());
#endif

Loading…
Cancel
Save