Browse Source

Merge branch 'dev' of https://github.com/abpframework/abp into dev

pull/12633/head
Ebicoglu 4 years ago
parent
commit
32c588e9b5
  1. 6
      docs/en/Microservice-Architecture.md
  2. 18
      docs/en/Samples/Index.md
  3. 2
      docs/en/Samples/Microservice-Demo.md
  4. 10
      docs/en/docs-nav.json
  5. 2
      docs/zh-Hans/Distributed-Event-Bus.md
  6. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxying/Angular/AngularServiceProxyGenerator.cs
  7. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Values/ValueObject.cs
  8. 25
      framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Values/EmailAddress.cs
  9. 5
      framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Values/ValueObject_Tests.cs
  10. 2
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json
  11. 2
      modules/blogging/app/Volo.BloggingTestApp/package.json
  12. 2
      modules/client-simulation/demo/Volo.ClientSimulation.Demo/package.json
  13. 2
      modules/cms-kit/host/Volo.CmsKit.IdentityServer/package.json
  14. 2
      modules/cms-kit/host/Volo.CmsKit.Web.Host/package.json
  15. 2
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/package.json
  16. 24
      modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs
  17. 9
      modules/cms-kit/test/Volo.CmsKit.TestBase/Comments/CommentRepository_Tests.cs
  18. 2
      modules/setting-management/src/Volo.Abp.SettingManagement.Application.Contracts/Volo/Abp/SettingManagement/IEmailSettingsAppService.cs
  19. 17
      modules/setting-management/src/Volo.Abp.SettingManagement.Application.Contracts/Volo/Abp/SettingManagement/SendTestEmailInput.cs
  20. 8
      modules/setting-management/src/Volo.Abp.SettingManagement.Application.Contracts/Volo/Abp/SettingManagement/SettingManagementPermissionDefinitionProvider.cs
  21. 2
      modules/setting-management/src/Volo.Abp.SettingManagement.Application.Contracts/Volo/Abp/SettingManagement/SettingManagementPermissions.cs
  22. 13
      modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo/Abp/SettingManagement/EmailSettingsAppService.cs
  23. 91
      modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor
  24. 76
      modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor.cs
  25. 2
      modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/SettingManagementBlazorAutoMapperProfile.cs
  26. 10
      modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json
  27. 10
      modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json
  28. 10
      modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json
  29. 10
      modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hant.json
  30. 8
      modules/setting-management/src/Volo.Abp.SettingManagement.HttpApi.Client/ClientProxies/EmailSettingsClientProxy.Generated.cs
  31. 39
      modules/setting-management/src/Volo.Abp.SettingManagement.HttpApi.Client/ClientProxies/settingManagement-generate-proxy.json
  32. 6
      modules/setting-management/src/Volo.Abp.SettingManagement.HttpApi/Volo/Abp/SettingManagement/EmailSettingsController.cs
  33. 9
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml
  34. 31
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.js
  35. 31
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/SendTestEmailModal.cshtml
  36. 59
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/SendTestEmailModal.cshtml.cs
  37. 2
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/SettingManagementWebAutoMapperProfile.cs
  38. 9
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/wwwroot/client-proxies/settingManagement-proxy.js
  39. 5
      modules/users/src/Volo.Abp.Users.Abstractions/Volo/Abp/Users/UserEto.cs
  40. 2
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/package.json
  41. 2
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/package.json
  42. 2
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/package.json
  43. 2
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/package.json
  44. 2
      templates/app/angular/package.json
  45. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/package.json
  46. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/package.json
  47. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/package.json
  48. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/package.json
  49. 2
      templates/module/angular/package.json
  50. 2
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/package.json
  51. 2
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/package.json
  52. 2
      templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/package.json

6
docs/en/Microservice-Architecture.md

@ -23,8 +23,8 @@ One common advise to start a new solution is **always to start with a monolith**
However, developing such a well-modular application can be a problem since it is **hard to keep modules isolated** from each other as you would do it for microservices (see [Stefan Tilkov's article](https://martinfowler.com/articles/dont-start-monolith.html) about that). Microservice architecture naturally forces you to develop well isolated services, but in a modular monolithic application it's easy to tight couple modules to each other and design **weak module boundaries** and API contracts. However, developing such a well-modular application can be a problem since it is **hard to keep modules isolated** from each other as you would do it for microservices (see [Stefan Tilkov's article](https://martinfowler.com/articles/dont-start-monolith.html) about that). Microservice architecture naturally forces you to develop well isolated services, but in a modular monolithic application it's easy to tight couple modules to each other and design **weak module boundaries** and API contracts.
ABP can help you in that point by offerring a **microservice-compatible, strict module architecture** where your module is splitted into multiple layers/projects and developed in its own VS solution completely isolated and independent from other modules. Such a developed module is a natural microservice yet it can be easily plugged-in a monolithic application. See the [module development best practice guide](Best-Practices/Index.md) that offers a **microservice-first module design**. All [standard ABP modules](https://github.com/abpframework/abp/tree/master/modules) are developed based on this guide. So, you can use these modules by embedding into your monolithic solution or deploy them separately and use via remote APIs. They can share a single database or can have their own database based on your simple configuration. ABP can help you in that point by offering a **microservice-compatible, strict module architecture** where your module is split into multiple layers/projects and developed in its own VS solution completely isolated and independent from other modules. Such a developed module is a natural microservice yet it can be easily plugged-in a monolithic application. See the [module development best practice guide](Best-Practices/Index.md) that offers a **microservice-first module design**. All [standard ABP modules](https://github.com/abpframework/abp/tree/master/modules) are developed based on this guide. So, you can use these modules by embedding into your monolithic solution or deploy them separately and use via remote APIs. They can share a single database or can have their own database based on your simple configuration.
## Microservice Demo Solution ## Microservice Demo Solution: eShopOnAbp
The [sample microservice solution](Samples/Microservice-Demo.md) demonstrates a complete microservice solution based on the ABP framework. The [eShopOnAbp project](https://github.com/abpframework/eShopOnAbp) demonstrates a complete microservice solution based on the ABP framework.

18
docs/en/Samples/Index.md

@ -2,15 +2,19 @@
Here, a list of official samples built with the ABP Framework. Most of these samples are located under the [abpframework/abp-samples](https://github.com/abpframework/abp-samples) GitHub repository. Here, a list of official samples built with the ABP Framework. Most of these samples are located under the [abpframework/abp-samples](https://github.com/abpframework/abp-samples) GitHub repository.
### Microservice Demo ## eShopOnAbp
A complete solution to demonstrate how to build systems based on the microservice architecture. Reference microservice solution built with the ABP Framework and .NET.
* [The complete documentation for this sample](Microservice-Demo.md) * [Source code](https://github.com/abpframework/eShopOnAbp)
* [Source code](https://github.com/abpframework/abp-samples/tree/master/MicroserviceDemo)
* [Microservice architecture document](../Microservice-Architecture.md)
### Book Store ## EventHub
This is a reference application built with the ABP Framework. It implements the Domain Driven Design with multiple application layers.
* [Source code](https://github.com/abpframework/eventhub)
## Book Store
A simple CRUD application to show basic principles of developing an application with the ABP Framework. The same sample was implemented with different technologies: A simple CRUD application to show basic principles of developing an application with the ABP Framework. The same sample was implemented with different technologies:
@ -28,7 +32,7 @@ A simple CRUD application to show basic principles of developing an application
While there is no Razor Pages & MongoDB combination, you can check both documents to understand it since DB & UI selection don't effect each other. While there is no Razor Pages & MongoDB combination, you can check both documents to understand it since DB & UI selection don't effect each other.
### Other Samples ## Other Samples
* **Event Organizer**: A sample application to create events (meetups) and allow others to register the events. Developed using EF Core and Blazor UI. * **Event Organizer**: A sample application to create events (meetups) and allow others to register the events. Developed using EF Core and Blazor UI.
* [Source code](https://github.com/abpframework/abp-samples/tree/master/EventOrganizer) * [Source code](https://github.com/abpframework/abp-samples/tree/master/EventOrganizer)

2
docs/en/Samples/Microservice-Demo.md

@ -1,5 +1,7 @@
# Microservice Demo Solution # Microservice Demo Solution
> This solution is no longer maintained. See [the eShopOnAbp project](https://github.com/abpframework/eShopOnAbp) for the replacement solution.
*"Microservices are a software development technique—a variant of the **service-oriented architecture** (SOA) architectural style that structures an application as a collection of **loosely coupled services**. In a microservices architecture, services are **fine-grained** and the protocols are **lightweight**. The benefit of decomposing an application into different smaller services is that it improves **modularity**. This makes the application easier to understand, develop, test, and become more resilient to architecture erosion. It **parallelizes development** by enabling small autonomous teams to **develop, deploy and scale** their respective services independently. It also allows the architecture of an individual service to emerge through **continuous refactoring**. Microservices-based architectures enable **continuous delivery and deployment**."* *"Microservices are a software development technique—a variant of the **service-oriented architecture** (SOA) architectural style that structures an application as a collection of **loosely coupled services**. In a microservices architecture, services are **fine-grained** and the protocols are **lightweight**. The benefit of decomposing an application into different smaller services is that it improves **modularity**. This makes the application easier to understand, develop, test, and become more resilient to architecture erosion. It **parallelizes development** by enabling small autonomous teams to **develop, deploy and scale** their respective services independently. It also allows the architecture of an individual service to emerge through **continuous refactoring**. Microservices-based architectures enable **continuous delivery and deployment**."*
— [Wikipedia](https://en.wikipedia.org/wiki/Microservices) — [Wikipedia](https://en.wikipedia.org/wiki/Microservices)

10
docs/en/docs-nav.json

@ -1320,7 +1320,15 @@
"path": "Samples/Index.md" "path": "Samples/Index.md"
}, },
{ {
"text": "Microservice Demo", "text": "eShopOnAbp",
"path": "https://github.com/abpframework/eShopOnAbp"
},
{
"text": "EventHub",
"path": "https://github.com/abpframework/eventhub"
},
{
"text": "Microservice Demo (legacy)",
"path": "Samples/Microservice-Demo.md" "path": "Samples/Microservice-Demo.md"
} }
] ]

2
docs/zh-Hans/Distributed-Event-Bus.md

@ -84,7 +84,7 @@ namespace AbpDemo
#### 关于序列化的事件对象 #### 关于序列化的事件对象
事件传输对象**必须是可序列化**的,因为将其传输到流程外时,它们将被序列化/反序列化为JSON或其他格式. 事件传输对象**必须是可序列化**的,因为将其传输到进程外时,它们将被序列化/反序列化为JSON或其他格式.
避免循环引用,多态,私有setter,并提供默认(空)构造函数,如果你有其他的构造函数.(虽然某些序列化器可能会正常工作),就像DTO一样. 避免循环引用,多态,私有setter,并提供默认(空)构造函数,如果你有其他的构造函数.(虽然某些序列化器可能会正常工作),就像DTO一样.

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxying/Angular/AngularServiceProxyGenerator.cs

@ -48,7 +48,7 @@ public class AngularServiceProxyGenerator : ServiceProxyGeneratorBase<AngularSer
var apiName = args.ApiName ?? defaultValue; var apiName = args.ApiName ?? defaultValue;
var source = args.Source ?? defaultValue; var source = args.Source ?? defaultValue;
var target = args.Target ?? defaultValue; var target = args.Target ?? defaultValue;
var url = args.Url ?? "''"; var url = args.Url ?? defaultValue;
var commandBuilder = new StringBuilder("npx ng g @abp/ng.schematics:" + schematicsCommandName); var commandBuilder = new StringBuilder("npx ng g @abp/ng.schematics:" + schematicsCommandName);
if (module != null) if (module != null)

2
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Values/ValueObject.cs

@ -44,6 +44,6 @@ public abstract class ValueObject
} }
} }
return !thisValues.MoveNext() && !otherValues.MoveNext(); return !thisMoveNext && !otherMoveNext;
} }
} }

25
framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Values/EmailAddress.cs

@ -0,0 +1,25 @@
using System.Collections.Generic;
namespace Volo.Abp.Domain.Values;
public class EmailAddress : ValueObject
{
public string Email { get; }
private EmailAddress()
{
}
public EmailAddress(string email)
{
Email = email;
}
protected override IEnumerable<object> GetAtomicValues()
{
if (Email != null)
{
yield return Email;
}
}
}

5
framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Values/ValueObject_Tests.cs

@ -31,5 +31,10 @@ public class ValueObject_Tests
address2 = new Address(cityId, "Baris Manco", 42, "home"); address2 = new Address(cityId, "Baris Manco", 42, "home");
address1.ValueEquals(address2).ShouldBeFalse(); address1.ValueEquals(address2).ShouldBeFalse();
var emailAddress1 = new EmailAddress("test@abp.io");
var emailAddress2 = new EmailAddress(null);
emailAddress1.ValueEquals(emailAddress2).ShouldBeFalse();
} }
} }

2
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json

@ -7,4 +7,4 @@
"highlight.js": "^9.13.1" "highlight.js": "^9.13.1"
}, },
"devDependencies": {} "devDependencies": {}
} }

2
modules/blogging/app/Volo.BloggingTestApp/package.json

@ -6,4 +6,4 @@
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1", "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1",
"@abp/blogging": "^5.3.0-rc.1" "@abp/blogging": "^5.3.0-rc.1"
} }
} }

2
modules/client-simulation/demo/Volo.ClientSimulation.Demo/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1"
} }
} }

2
modules/cms-kit/host/Volo.CmsKit.IdentityServer/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1"
} }
} }

2
modules/cms-kit/host/Volo.CmsKit.Web.Host/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1"
} }
} }

2
modules/cms-kit/host/Volo.CmsKit.Web.Unified/package.json

@ -6,4 +6,4 @@
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1", "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1",
"@abp/cms-kit": "5.3.0-rc.1" "@abp/cms-kit": "5.3.0-rc.1"
} }
} }

24
modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Comments/MongoCommentRepository.cs

@ -7,7 +7,6 @@ using System.Threading.Tasks;
using MongoDB.Driver; using MongoDB.Driver;
using MongoDB.Driver.Linq; using MongoDB.Driver.Linq;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB; using Volo.Abp.MongoDB;
using Volo.CmsKit.Comments; using Volo.CmsKit.Comments;
@ -23,25 +22,16 @@ public class MongoCommentRepository : MongoDbRepository<ICmsKitMongoDbContext, C
public virtual async Task<CommentWithAuthorQueryResultItem> GetWithAuthorAsync(Guid id, CancellationToken cancellationToken = default) public virtual async Task<CommentWithAuthorQueryResultItem> GetWithAuthorAsync(Guid id, CancellationToken cancellationToken = default)
{ {
var query = from comment in (await GetMongoQueryableAsync(cancellationToken)) var comment = await GetAsync(id);
join user in (await GetDbContextAsync(cancellationToken)).CmsUsers on comment.CreatorId equals user.Id var author = await (await GetDbContextAsync())
where id == comment.Id .CmsUsers
select new { .AsQueryable()
Comment = comment, .FirstOrDefaultAsync(x => x.Id == comment.CreatorId, GetCancellationToken(cancellationToken));
Author = user
};
var commentWithAuthor = await query.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
if (commentWithAuthor == null)
{
throw new EntityNotFoundException(typeof(Comment), id);
}
return new CommentWithAuthorQueryResultItem() return new CommentWithAuthorQueryResultItem()
{ {
Comment = commentWithAuthor.Comment, Comment = comment,
Author = commentWithAuthor.Author Author = author
}; };
} }

9
modules/cms-kit/test/Volo.CmsKit.TestBase/Comments/CommentRepository_Tests.cs

@ -54,6 +54,15 @@ public abstract class CommentRepository_Tests<TStartupModule> : CmsKitTestBase<T
list.Any(x => x.Author == null).ShouldBeFalse(); list.Any(x => x.Author == null).ShouldBeFalse();
} }
[Fact]
public async Task GetWithAuthorAsync()
{
var commentDetail = await _commentRepository.GetWithAuthorAsync(_cmsKitTestData.CommentWithChildId);
commentDetail.ShouldNotBeNull();
commentDetail.Author.ShouldNotBeNull();
}
[Fact] [Fact]
public async Task DeleteWithRepliesAsync() public async Task DeleteWithRepliesAsync()
{ {

2
modules/setting-management/src/Volo.Abp.SettingManagement.Application.Contracts/Volo/Abp/SettingManagement/IEmailSettingsAppService.cs

@ -8,4 +8,6 @@ public interface IEmailSettingsAppService : IApplicationService
Task<EmailSettingsDto> GetAsync(); Task<EmailSettingsDto> GetAsync();
Task UpdateAsync(UpdateEmailSettingsDto input); Task UpdateAsync(UpdateEmailSettingsDto input);
Task SendTestEmailAsync(SendTestEmailInput input);
} }

17
modules/setting-management/src/Volo.Abp.SettingManagement.Application.Contracts/Volo/Abp/SettingManagement/SendTestEmailInput.cs

@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
namespace Volo.Abp.SettingManagement;
public class SendTestEmailInput
{
[Required]
public string SenderEmailAddress { get; set; }
[Required]
public string TargetEmailAddress { get; set; }
[Required]
public string Subject { get; set; }
public string Body { get; set; }
}

8
modules/setting-management/src/Volo.Abp.SettingManagement.Application.Contracts/Volo/Abp/SettingManagement/SettingManagementPermissionDefinitionProvider.cs

@ -10,9 +10,11 @@ public class SettingManagementPermissionDefinitionProvider : PermissionDefinitio
{ {
var moduleGroup = context.AddGroup(SettingManagementPermissions.GroupName, L("Permission:SettingManagement")); var moduleGroup = context.AddGroup(SettingManagementPermissions.GroupName, L("Permission:SettingManagement"));
moduleGroup var emailPermission = moduleGroup
.AddPermission(SettingManagementPermissions.Emailing, L("Permission:Emailing")) .AddPermission(SettingManagementPermissions.Emailing, L("Permission:Emailing"));
.StateCheckers.Add(new AllowTenantsToChangeEmailSettingsFeatureSimpleStateChecker()); emailPermission.StateCheckers.Add(new AllowTenantsToChangeEmailSettingsFeatureSimpleStateChecker());
emailPermission.AddChild(SettingManagementPermissions.EmailingTest, L("Permission:EmailingTest"));
} }
private static LocalizableString L(string name) private static LocalizableString L(string name)

2
modules/setting-management/src/Volo.Abp.SettingManagement.Application.Contracts/Volo/Abp/SettingManagement/SettingManagementPermissions.cs

@ -7,6 +7,8 @@ public class SettingManagementPermissions
public const string GroupName = "SettingManagement"; public const string GroupName = "SettingManagement";
public const string Emailing = GroupName + ".Emailing"; public const string Emailing = GroupName + ".Emailing";
public const string EmailingTest = Emailing + ".Test";
public static string[] GetAll() public static string[] GetAll()
{ {

13
modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo/Abp/SettingManagement/EmailSettingsAppService.cs

@ -11,10 +11,13 @@ namespace Volo.Abp.SettingManagement;
public class EmailSettingsAppService : SettingManagementAppServiceBase, IEmailSettingsAppService public class EmailSettingsAppService : SettingManagementAppServiceBase, IEmailSettingsAppService
{ {
protected ISettingManager SettingManager { get; } protected ISettingManager SettingManager { get; }
protected IEmailSender EmailSender { get; }
public EmailSettingsAppService(ISettingManager settingManager) public EmailSettingsAppService(ISettingManager settingManager, IEmailSender emailSender)
{ {
SettingManager = settingManager; SettingManager = settingManager;
EmailSender = emailSender;
} }
public virtual async Task<EmailSettingsDto> GetAsync() public virtual async Task<EmailSettingsDto> GetAsync()
@ -60,6 +63,14 @@ public class EmailSettingsAppService : SettingManagementAppServiceBase, IEmailSe
await SettingManager.SetForTenantOrGlobalAsync(CurrentTenant.Id, EmailSettingNames.DefaultFromDisplayName, input.DefaultFromDisplayName); await SettingManager.SetForTenantOrGlobalAsync(CurrentTenant.Id, EmailSettingNames.DefaultFromDisplayName, input.DefaultFromDisplayName);
} }
[Authorize(SettingManagementPermissions.EmailingTest)]
public virtual async Task SendTestEmailAsync(SendTestEmailInput input)
{
await CheckFeatureAsync();
await EmailSender.SendAsync(input.SenderEmailAddress, input.TargetEmailAddress, input.Subject, input.Body);
}
protected virtual async Task CheckFeatureAsync() protected virtual async Task CheckFeatureAsync()
{ {
await FeatureChecker.CheckEnabledAsync(SettingManagementFeatures.Enable); await FeatureChecker.CheckEnabledAsync(SettingManagementFeatures.Enable);

91
modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor

@ -13,7 +13,7 @@
<FieldLabel>@L["DefaultFromDisplayName"] *</FieldLabel> <FieldLabel>@L["DefaultFromDisplayName"] *</FieldLabel>
<TextEdit @bind-Text="@EmailSettings.DefaultFromDisplayName"> <TextEdit @bind-Text="@EmailSettings.DefaultFromDisplayName">
<Feedback> <Feedback>
<ValidationError /> <ValidationError/>
</Feedback> </Feedback>
</TextEdit> </TextEdit>
</Field> </Field>
@ -23,17 +23,17 @@
<FieldLabel>@L["DefaultFromAddress"] *</FieldLabel> <FieldLabel>@L["DefaultFromAddress"] *</FieldLabel>
<TextEdit @bind-Text="@EmailSettings.DefaultFromAddress"> <TextEdit @bind-Text="@EmailSettings.DefaultFromAddress">
<Feedback> <Feedback>
<ValidationError /> <ValidationError/>
</Feedback> </Feedback>
</TextEdit> </TextEdit>
</Field> </Field>
</Validation> </Validation>
<Validation MessageLocalizer="@LH.Localize"> <Validation MessageLocalizer="@LH.Localize">
<Field> <Field>
<FieldLabel>@L["SmtpHost"]</FieldLabel> <FieldLabel>@L["SmtpHost"]</FieldLabel>
<TextEdit @bind-Text="@EmailSettings.SmtpHost"> <TextEdit @bind-Text="@EmailSettings.SmtpHost">
<Feedback> <Feedback>
<ValidationError /> <ValidationError/>
</Feedback> </Feedback>
</TextEdit> </TextEdit>
</Field> </Field>
@ -58,30 +58,30 @@
{ {
<Validation MessageLocalizer="@LH.Localize"> <Validation MessageLocalizer="@LH.Localize">
<Field> <Field>
<FieldLabel>@L["SmtpDomain"]</FieldLabel> <FieldLabel>@L["SmtpDomain"]</FieldLabel>
<TextEdit @bind-Text="@EmailSettings.SmtpDomain"> <TextEdit @bind-Text="@EmailSettings.SmtpDomain">
<Feedback> <Feedback>
<ValidationError /> <ValidationError/>
</Feedback> </Feedback>
</TextEdit> </TextEdit>
</Field> </Field>
</Validation> </Validation>
<Validation MessageLocalizer="@LH.Localize"> <Validation MessageLocalizer="@LH.Localize">
<Field> <Field>
<FieldLabel>@L["SmtpUserName"]</FieldLabel> <FieldLabel>@L["SmtpUserName"]</FieldLabel>
<TextEdit @bind-Text="@EmailSettings.SmtpUserName"> <TextEdit @bind-Text="@EmailSettings.SmtpUserName">
<Feedback> <Feedback>
<ValidationError /> <ValidationError/>
</Feedback> </Feedback>
</TextEdit> </TextEdit>
</Field> </Field>
</Validation> </Validation>
<Validation MessageLocalizer="@LH.Localize"> <Validation MessageLocalizer="@LH.Localize">
<Field> <Field>
<FieldLabel>@L["SmtpPassword"]</FieldLabel> <FieldLabel>@L["SmtpPassword"]</FieldLabel>
<TextEdit Role="TextRole.Password" @bind-Text="@EmailSettings.SmtpPassword"> <TextEdit Role="TextRole.Password" @bind-Text="@EmailSettings.SmtpPassword">
<Feedback> <Feedback>
<ValidationError /> <ValidationError/>
</Feedback> </Feedback>
</TextEdit> </TextEdit>
</Field> </Field>
@ -92,8 +92,75 @@
</Validations> </Validations>
<Row> <Row>
<Column> <Column>
<SubmitButton Clicked="@UpdateSettingsAsync" /> <SubmitButton Clicked="@UpdateSettingsAsync"/>
@if (HasSendTestEmailPermission)
{
<Button style="margin: 0.25rem" Color="Color.Primary" Clicked="OpenSendTestEmailModalAsync">@L["SendTestEmail"]</Button>
}
</Column> </Column>
</Row> </Row>
</Form> </Form>
}
@if (HasSendTestEmailPermission)
{
<Modal @ref="SendTestEmailModal">
<ModalContent Centered="true">
<Form>
<ModalHeader>
<ModalTitle>@L["SendTestEmail"]</ModalTitle>
<CloseButton Clicked="CloseSendTestEmailModalAsync"/>
</ModalHeader>
<ModalBody>
<Validations @ref="@EmailSettingTestValidation" Model="@SendTestEmailInput" ValidateOnLoad="false">
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["SenderEmailAddress"]</FieldLabel>
<TextEdit @bind-Text="@SendTestEmailInput.SenderEmailAddress" Autofocus="true">
<Feedback>
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["TargetEmailAddress"]</FieldLabel>
<TextEdit @bind-Text="@SendTestEmailInput.TargetEmailAddress">
<Feedback>
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["Subject"]</FieldLabel>
<TextEdit @bind-Text="@SendTestEmailInput.Subject">
<Feedback>
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["Body"]</FieldLabel>
<TextEdit @bind-Text="@SendTestEmailInput.Body">
<Feedback>
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
</Validation>
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary" Clicked="CloseSendTestEmailModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary" Clicked="SendTestEmailAsync">@L["Send"]</Button>
</ModalFooter>
</Form>
</ModalContent>
</Modal>
}
}

76
modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/EmailSettingGroup/EmailSettingGroupViewComponent.razor.cs

@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Components;
using Volo.Abp.AspNetCore.Components.Messages; using Volo.Abp.AspNetCore.Components.Messages;
using Volo.Abp.AspNetCore.Components.Web.Configuration; using Volo.Abp.AspNetCore.Components.Web.Configuration;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.SettingManagement.Localization; using Volo.Abp.SettingManagement.Localization;
namespace Volo.Abp.SettingManagement.Blazor.Pages.SettingManagement.EmailSettingGroup; namespace Volo.Abp.SettingManagement.Blazor.Pages.SettingManagement.EmailSettingGroup;
@ -14,6 +15,9 @@ public partial class EmailSettingGroupViewComponent
{ {
[Inject] [Inject]
protected IEmailSettingsAppService EmailSettingsAppService { get; set; } protected IEmailSettingsAppService EmailSettingsAppService { get; set; }
[Inject]
protected IPermissionChecker PermissionChecker { get; set; }
[Inject] [Inject]
private ICurrentApplicationConfigurationCacheResetService CurrentApplicationConfigurationCacheResetService { get; set; } private ICurrentApplicationConfigurationCacheResetService CurrentApplicationConfigurationCacheResetService { get; set; }
@ -23,7 +27,17 @@ public partial class EmailSettingGroupViewComponent
protected UpdateEmailSettingsViewModel EmailSettings; protected UpdateEmailSettingsViewModel EmailSettings;
protected SendTestEmailViewModel SendTestEmailInput;
protected Validations EmailSettingValidation; protected Validations EmailSettingValidation;
protected Validations EmailSettingTestValidation;
protected Modal SendTestEmailModal;
protected bool HasSendTestEmailPermission { get; set; }
public EmailSettingGroupViewComponent() public EmailSettingGroupViewComponent()
{ {
@ -36,6 +50,8 @@ public partial class EmailSettingGroupViewComponent
try try
{ {
EmailSettings = ObjectMapper.Map<EmailSettingsDto, UpdateEmailSettingsViewModel>(await EmailSettingsAppService.GetAsync()); EmailSettings = ObjectMapper.Map<EmailSettingsDto, UpdateEmailSettingsViewModel>(await EmailSettingsAppService.GetAsync());
HasSendTestEmailPermission = await PermissionChecker.IsGrantedAsync(SettingManagementPermissions.EmailingTest);
SendTestEmailInput = new SendTestEmailViewModel();
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -64,6 +80,52 @@ public partial class EmailSettingGroupViewComponent
} }
} }
protected virtual async Task OpenSendTestEmailModalAsync()
{
try
{
await EmailSettingTestValidation.ClearAll();
var emailSettings = await EmailSettingsAppService.GetAsync();
SendTestEmailInput = new SendTestEmailViewModel
{
SenderEmailAddress = emailSettings.DefaultFromAddress,
TargetEmailAddress = CurrentUser.Email,
Subject = L["TestEmailSubject", new Random().Next(1000, 9999)],
Body = L["TestEmailBody"]
};
await SendTestEmailModal.Show();
}
catch (Exception ex)
{
await HandleErrorAsync(ex);
}
}
protected virtual Task CloseSendTestEmailModalAsync()
{
return InvokeAsync(SendTestEmailModal.Hide);
}
protected virtual async Task SendTestEmailAsync()
{
try
{
if (!await EmailSettingTestValidation.ValidateAll())
{
return;
}
await EmailSettingsAppService.SendTestEmailAsync(ObjectMapper.Map<SendTestEmailViewModel, SendTestEmailInput>(SendTestEmailInput));
await Notify.Success(L["SuccessfullySent"]);
}
catch (Exception ex)
{
await HandleErrorAsync(ex);
}
}
public class UpdateEmailSettingsViewModel public class UpdateEmailSettingsViewModel
{ {
[MaxLength(256)] [MaxLength(256)]
@ -104,4 +166,18 @@ public partial class EmailSettingGroupViewComponent
[Display(Name = "DefaultFromDisplayName")] [Display(Name = "DefaultFromDisplayName")]
public string DefaultFromDisplayName { get; set; } public string DefaultFromDisplayName { get; set; }
} }
public class SendTestEmailViewModel
{
[Required]
public string SenderEmailAddress { get; set; }
[Required]
public string TargetEmailAddress { get; set; }
[Required]
public string Subject { get; set; }
public string Body { get; set; }
}
} }

2
modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/SettingManagementBlazorAutoMapperProfile.cs

@ -9,5 +9,7 @@ public class SettingManagementBlazorAutoMapperProfile : Profile
{ {
CreateMap<EmailSettingGroupViewComponent.UpdateEmailSettingsViewModel, UpdateEmailSettingsDto>(); CreateMap<EmailSettingGroupViewComponent.UpdateEmailSettingsViewModel, UpdateEmailSettingsDto>();
CreateMap<EmailSettingsDto, EmailSettingGroupViewComponent.UpdateEmailSettingsViewModel>(); CreateMap<EmailSettingsDto, EmailSettingGroupViewComponent.UpdateEmailSettingsViewModel>();
CreateMap<EmailSettingGroupViewComponent.SendTestEmailViewModel, SendTestEmailInput>();
} }
} }

10
modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json

@ -5,6 +5,16 @@
"SuccessfullySaved": "Successfully saved", "SuccessfullySaved": "Successfully saved",
"Permission:SettingManagement": "Setting Management", "Permission:SettingManagement": "Setting Management",
"Permission:Emailing": "Emailing", "Permission:Emailing": "Emailing",
"Permission:EmailingTest": "Emailing test",
"SendTestEmail": "Send test email",
"SenderEmailAddress": "Sender email address",
"TargetEmailAddress": "Target email address",
"Subject": "Subject",
"Body": "Body",
"TestEmailSubject": "Test email {0}",
"TestEmailBody": "Test email body message here",
"SuccessfullySent": "Successfully sent",
"Send": "Send",
"Menu:Emailing": "Emailing", "Menu:Emailing": "Emailing",
"SmtpHost": "Host", "SmtpHost": "Host",
"SmtpPort": "Port", "SmtpPort": "Port",

10
modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json

@ -5,6 +5,16 @@
"SuccessfullySaved": "Başarıyla Kaydedildi", "SuccessfullySaved": "Başarıyla Kaydedildi",
"Permission:SettingManagement": "Ayarlar yönetimi", "Permission:SettingManagement": "Ayarlar yönetimi",
"Permission:Emailing": "Email", "Permission:Emailing": "Email",
"Permission:EmailingTest": "Email testi",
"SendTestEmail": "Test emaili gönder",
"SenderEmailAddress": "Gönderen email adresi",
"TargetEmailAddress": "Hedef email adresi",
"Subject": "Konu",
"Body": "Gövde",
"TestEmailSubject": "Test email {0}",
"TestEmailBody": "E-posta gövdesi mesajını burada test edin",
"SuccessfullySent": "Başarıyla gönderildi",
"Send": "Gönder",
"Menu:Emailing": "Email", "Menu:Emailing": "Email",
"SmtpHost": "Sunucu", "SmtpHost": "Sunucu",
"SmtpPort": "Port", "SmtpPort": "Port",

10
modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json

@ -5,6 +5,16 @@
"SuccessfullySaved": "保存成功", "SuccessfullySaved": "保存成功",
"Permission:SettingManagement": "设置管理", "Permission:SettingManagement": "设置管理",
"Permission:Emailing": "邮件", "Permission:Emailing": "邮件",
"Permission:EmailingTest": "邮件测试",
"SendTestEmail": "发送测试邮件",
"SenderEmailAddress": "发件人邮箱地址",
"TargetEmailAddress": "收件人邮箱地址",
"Subject": "主题",
"Body": "正文",
"TestEmailSubject": "测试邮件 {0}",
"TestEmailBody": "测试邮件内容",
"SuccessfullySent": "发送成功",
"Send": "发送",
"Menu:Emailing": "邮件", "Menu:Emailing": "邮件",
"SmtpHost": "主机", "SmtpHost": "主机",
"SmtpPort": "端口", "SmtpPort": "端口",

10
modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hant.json

@ -5,6 +5,16 @@
"SuccessfullySaved": "保存成功", "SuccessfullySaved": "保存成功",
"Permission:SettingManagement": "設定管理", "Permission:SettingManagement": "設定管理",
"Permission:Emailing": "信箱", "Permission:Emailing": "信箱",
"Permission:EmailingTest": "邮件測試",
"SendTestEmail": "發送測試邮件",
"SenderEmailAddress": "發送者電子郵件地址",
"TargetEmailAddress": "目標電子郵件地址",
"Subject": "主題",
"Body": "體",
"TestEmailSubject": "測試邮件 {0}",
"TestEmailBody": "測試邮件內容",
"SuccessfullySent": "成功發送",
"Send": "發送",
"Menu:Emailing": "信箱", "Menu:Emailing": "信箱",
"SmtpHost": "主機", "SmtpHost": "主機",
"SmtpPort": "Port", "SmtpPort": "Port",

8
modules/setting-management/src/Volo.Abp.SettingManagement.HttpApi.Client/ClientProxies/EmailSettingsClientProxy.Generated.cs

@ -27,4 +27,12 @@ public partial class EmailSettingsClientProxy : ClientProxyBase<IEmailSettingsAp
{ typeof(UpdateEmailSettingsDto), input } { typeof(UpdateEmailSettingsDto), input }
}); });
} }
public virtual async Task SendTestEmailAsync(SendTestEmailInput input)
{
await RequestAsync(nameof(SendTestEmailAsync), new ClientProxyRequestTypeValue
{
{ typeof(SendTestEmailInput), input }
});
}
} }

39
modules/setting-management/src/Volo.Abp.SettingManagement.HttpApi.Client/ClientProxies/settingManagement-generate-proxy.json

@ -7,6 +7,8 @@
"Volo.Abp.SettingManagement.EmailSettingsController": { "Volo.Abp.SettingManagement.EmailSettingsController": {
"controllerName": "EmailSettings", "controllerName": "EmailSettings",
"controllerGroupName": "EmailSettings", "controllerGroupName": "EmailSettings",
"isRemoteService": true,
"apiVersion": null,
"type": "Volo.Abp.SettingManagement.EmailSettingsController", "type": "Volo.Abp.SettingManagement.EmailSettingsController",
"interfaces": [ "interfaces": [
{ {
@ -65,6 +67,43 @@
}, },
"allowAnonymous": null, "allowAnonymous": null,
"implementFrom": "Volo.Abp.SettingManagement.IEmailSettingsAppService" "implementFrom": "Volo.Abp.SettingManagement.IEmailSettingsAppService"
},
"SendTestEmailAsyncByInput": {
"uniqueName": "SendTestEmailAsyncByInput",
"name": "SendTestEmailAsync",
"httpMethod": "POST",
"url": "api/setting-management/emailing/send-test-email",
"supportedVersions": [],
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "Volo.Abp.SettingManagement.SendTestEmailInput, Volo.Abp.SettingManagement.Application.Contracts",
"type": "Volo.Abp.SettingManagement.SendTestEmailInput",
"typeSimple": "Volo.Abp.SettingManagement.SendTestEmailInput",
"isOptional": false,
"defaultValue": null
}
],
"parameters": [
{
"nameOnMethod": "input",
"name": "input",
"jsonName": null,
"type": "Volo.Abp.SettingManagement.SendTestEmailInput",
"typeSimple": "Volo.Abp.SettingManagement.SendTestEmailInput",
"isOptional": false,
"defaultValue": null,
"constraintTypes": null,
"bindingSourceId": "Body",
"descriptorName": ""
}
],
"returnValue": {
"type": "System.Void",
"typeSimple": "System.Void"
},
"allowAnonymous": null,
"implementFrom": "Volo.Abp.SettingManagement.IEmailSettingsAppService"
} }
} }
} }

6
modules/setting-management/src/Volo.Abp.SettingManagement.HttpApi/Volo/Abp/SettingManagement/EmailSettingsController.cs

@ -27,4 +27,10 @@ public class EmailSettingsController : AbpControllerBase, IEmailSettingsAppServi
{ {
return _emailSettingsAppService.UpdateAsync(input); return _emailSettingsAppService.UpdateAsync(input);
} }
[HttpPost("send-test-email")]
public Task SendTestEmailAsync(SendTestEmailInput input)
{
return _emailSettingsAppService.SendTestEmailAsync(input);
}
} }

9
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.cshtml

@ -1,6 +1,9 @@
@using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Authorization.Permissions
@using Volo.Abp.SettingManagement
@using Volo.Abp.SettingManagement.Localization @using Volo.Abp.SettingManagement.Localization
@inject IHtmlLocalizer<AbpSettingManagementResource> L @inject IHtmlLocalizer<AbpSettingManagementResource> L
@inject IPermissionChecker PermissionChecker
@model Volo.Abp.SettingManagement.Web.Pages.SettingManagement.Components.EmailSettingGroup.EmailSettingGroupViewComponent.UpdateEmailSettingsViewModel @model Volo.Abp.SettingManagement.Web.Pages.SettingManagement.Components.EmailSettingGroup.EmailSettingGroupViewComponent.UpdateEmailSettingsViewModel
<form id="EmailSettingsForm" method="post"> <form id="EmailSettingsForm" method="post">
@ -24,6 +27,12 @@
<abp-button button-type="Primary" type="submit"> <abp-button button-type="Primary" type="submit">
<i class="fa fa-save"></i> @L["Save"] <i class="fa fa-save"></i> @L["Save"]
</abp-button> </abp-button>
@if (await PermissionChecker.IsGrantedAsync(SettingManagementPermissions.EmailingTest))
{
<abp-button button-type="Primary" id="SendTestEmailButton">
<i class="fa fa-send"></i> @L["SendTestEmail"]
</abp-button>
}
</div> </div>
</abp-column> </abp-column>
</abp-row> </abp-row>

31
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/Default.js

@ -1,16 +1,20 @@
(function ($) { (function ($) {
var _sendTestEmailModal = new abp.ModalManager(
abp.appPath + 'SettingManagement/Components/EmailSettingGroup/SendTestEmailModal'
);
$(function () { $(function () {
var l = abp.localization.getResource('AbpSettingManagement'); var l = abp.localization.getResource('AbpSettingManagement');
$("#EmailSettingsForm").on('submit', function (event) { $("#EmailSettingsForm").on('submit', function (event) {
event.preventDefault(); event.preventDefault();
if(!$(this).valid()) { if (!$(this).valid()) {
return; return;
} }
var form = $(this).serializeFormToObject(); var form = $(this).serializeFormToObject();
volo.abp.settingManagement.emailSettings.update(form).then(function (result) { volo.abp.settingManagement.emailSettings.update(form).then(function (result) {
$(document).trigger("AbpSettingSaved"); $(document).trigger("AbpSettingSaved");
@ -21,11 +25,28 @@
$('#SmtpUseDefaultCredentials').change(function () { $('#SmtpUseDefaultCredentials').change(function () {
if (this.checked) { if (this.checked) {
$('#HideSectionWhenUseDefaultCredentialsIsChecked').slideUp(); $('#HideSectionWhenUseDefaultCredentialsIsChecked').slideUp();
} } else {
else {
$('#HideSectionWhenUseDefaultCredentialsIsChecked').slideDown(); $('#HideSectionWhenUseDefaultCredentialsIsChecked').slideDown();
} }
}); });
_sendTestEmailModal.onOpen(function () {
var $form = _sendTestEmailModal.getForm();
_sendTestEmailModal.getForm().off('abp-ajax-success');
$form.on('abp-ajax-success', function () {
_sendTestEmailModal.setResult();
});
})
_sendTestEmailModal.onResult(function () {
abp.notify.success(l('SuccessfullySent'));
});
$("#SendTestEmailButton").click(function (e) {
e.preventDefault();
_sendTestEmailModal.open();
});
}); });
})(jQuery); })(jQuery);

31
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/SendTestEmailModal.cshtml

@ -0,0 +1,31 @@
@page
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@using Volo.Abp.SettingManagement.Localization
@using Volo.Abp.SettingManagement.Web.Pages.SettingManagement.Components.EmailSettingGroup
@model SendTestEmailModal
@inject IHtmlLocalizer<AbpSettingManagementResource> L
@{
Layout = null;
}
<form asp-page="/SettingManagement/Components/EmailSettingGroup/SendTestEmailModal">
<abp-modal>
<abp-modal-header title="@L["SendTestEmail"].Value"></abp-modal-header>
<abp-modal-body>
<abp-input asp-for="Input.SenderEmailAddress" />
<abp-input asp-for="Input.TargetEmailAddress" />
<abp-input asp-for="Input.Subject" />
<abp-input asp-for="Input.Body" />
</abp-modal-body>
<abp-modal-footer>
<abp-button data-bs-dismiss="modal" button-type="Secondary">@L["Cancel"]</abp-button>
<abp-button button-type="Primary" type="submit">
<i class="fa fa-send"></i> @L["Send"]
</abp-button>
</abp-modal-footer>
</abp-modal>
</form>

59
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/EmailSettingGroup/SendTestEmailModal.cshtml.cs

@ -0,0 +1,59 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.SettingManagement.Localization;
namespace Volo.Abp.SettingManagement.Web.Pages.SettingManagement.Components.EmailSettingGroup;
[Authorize(SettingManagementPermissions.EmailingTest)]
public class SendTestEmailModal : AbpPageModel
{
[BindProperty]
public SendTestEmailViewModel Input { get; set; }
protected IEmailSettingsAppService EmailSettingsAppService { get; }
public SendTestEmailModal(IEmailSettingsAppService emailSettingsAppService)
{
LocalizationResourceType = typeof(AbpSettingManagementResource);
EmailSettingsAppService = emailSettingsAppService;
}
public async Task OnGetAsync()
{
var emailSettings = await EmailSettingsAppService.GetAsync();
Input = new SendTestEmailViewModel
{
SenderEmailAddress = emailSettings.DefaultFromAddress,
TargetEmailAddress = CurrentUser.Email,
Subject = L["TestEmailSubject", new Random().Next(1000, 9999)],
Body = L["TestEmailBody"]
};
}
public async Task<IActionResult> OnPostAsync()
{
ValidateModel();
await EmailSettingsAppService.SendTestEmailAsync(ObjectMapper.Map<SendTestEmailViewModel, SendTestEmailInput>(Input));
return NoContent();
}
public class SendTestEmailViewModel
{
[Required]
public string SenderEmailAddress { get; set; }
[Required]
public string TargetEmailAddress { get; set; }
[Required]
public string Subject { get; set; }
public string Body { get; set; }
}
}

2
modules/setting-management/src/Volo.Abp.SettingManagement.Web/SettingManagementWebAutoMapperProfile.cs

@ -8,5 +8,7 @@ public class SettingManagementWebAutoMapperProfile : Profile
public SettingManagementWebAutoMapperProfile() public SettingManagementWebAutoMapperProfile()
{ {
CreateMap<EmailSettingsDto, EmailSettingGroupViewComponent.UpdateEmailSettingsViewModel>(); CreateMap<EmailSettingsDto, EmailSettingGroupViewComponent.UpdateEmailSettingsViewModel>();
CreateMap<SendTestEmailModal.SendTestEmailViewModel, SendTestEmailInput>();
} }
} }

9
modules/setting-management/src/Volo.Abp.SettingManagement.Web/wwwroot/client-proxies/settingManagement-proxy.js

@ -27,6 +27,15 @@
}, ajaxParams)); }, ajaxParams));
}; };
volo.abp.settingManagement.emailSettings.sendTestEmail = function(input, ajaxParams) {
return abp.ajax($.extend(true, {
url: abp.appPath + 'api/setting-management/emailing/send-test-email',
type: 'POST',
dataType: null,
data: JSON.stringify(input)
}, ajaxParams));
};
})(); })();
})(); })();

5
modules/users/src/Volo.Abp.Users.Abstractions/Volo/Abp/Users/UserEto.cs

@ -1,10 +1,11 @@
using System; using System;
using Volo.Abp.Data;
using Volo.Abp.EventBus; using Volo.Abp.EventBus;
namespace Volo.Abp.Users; namespace Volo.Abp.Users;
[EventName("Volo.Abp.Users.User")] [EventName("Volo.Abp.Users.User")]
public class UserEto : IUserData public class UserEto : IUserData, IHasExtraProperties
{ {
public Guid Id { get; set; } public Guid Id { get; set; }
@ -23,4 +24,6 @@ public class UserEto : IUserData
public string PhoneNumber { get; set; } public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; } public bool PhoneNumberConfirmed { get; set; }
public ExtraPropertyDictionary ExtraProperties { get; set; }
} }

2
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1"
} }
} }

2
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1"
} }
} }

2
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "~5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "~5.3.0-rc.1"
} }
} }

2
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "~5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "~5.3.0-rc.1"
} }
} }

2
templates/app/angular/package.json

@ -58,4 +58,4 @@
"ng-packagr": "^13.1.2", "ng-packagr": "^13.1.2",
"typescript": "~4.5.4" "typescript": "~4.5.4"
} }
} }

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1"
} }
} }

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1"
} }
} }

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1"
} }
} }

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1"
} }
} }

2
templates/module/angular/package.json

@ -62,4 +62,4 @@
"symlink-manager": "^1.5.0", "symlink-manager": "^1.5.0",
"typescript": "~4.5.4" "typescript": "~4.5.4"
} }
} }

2
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1"
} }
} }

2
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1"
} }
} }

2
templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/package.json

@ -5,4 +5,4 @@
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1" "@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1"
} }
} }

Loading…
Cancel
Save