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.
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.
### 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/abp-samples/tree/master/MicroserviceDemo)
* [Microservice architecture document](../Microservice-Architecture.md)
* [Source code](https://github.com/abpframework/eShopOnAbp)
### 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:
@ -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.
### 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.
* [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
> 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**."*
— [Wikipedia](https://en.wikipedia.org/wiki/Microservices)

10
docs/en/docs-nav.json

@ -1320,7 +1320,15 @@
"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"
}
]

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

@ -84,7 +84,7 @@ namespace AbpDemo
#### 关于序列化的事件对象
事件传输对象**必须是可序列化**的,因为将其传输到程外时,它们将被序列化/反序列化为JSON或其他格式.
事件传输对象**必须是可序列化**的,因为将其传输到程外时,它们将被序列化/反序列化为JSON或其他格式.
避免循环引用,多态,私有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 source = args.Source ?? 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);
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");
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"
},
"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/blogging": "^5.3.0-rc.1"
}
}
}

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

@ -5,4 +5,4 @@
"dependencies": {
"@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": {
"@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": {
"@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/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.Linq;
using Volo.Abp;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB;
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)
{
var query = from comment in (await GetMongoQueryableAsync(cancellationToken))
join user in (await GetDbContextAsync(cancellationToken)).CmsUsers on comment.CreatorId equals user.Id
where id == comment.Id
select new {
Comment = comment,
Author = user
};
var commentWithAuthor = await query.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
if (commentWithAuthor == null)
{
throw new EntityNotFoundException(typeof(Comment), id);
}
var comment = await GetAsync(id);
var author = await (await GetDbContextAsync())
.CmsUsers
.AsQueryable()
.FirstOrDefaultAsync(x => x.Id == comment.CreatorId, GetCancellationToken(cancellationToken));
return new CommentWithAuthorQueryResultItem()
{
Comment = commentWithAuthor.Comment,
Author = commentWithAuthor.Author
Comment = comment,
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();
}
[Fact]
public async Task GetWithAuthorAsync()
{
var commentDetail = await _commentRepository.GetWithAuthorAsync(_cmsKitTestData.CommentWithChildId);
commentDetail.ShouldNotBeNull();
commentDetail.Author.ShouldNotBeNull();
}
[Fact]
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 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"));
moduleGroup
.AddPermission(SettingManagementPermissions.Emailing, L("Permission:Emailing"))
.StateCheckers.Add(new AllowTenantsToChangeEmailSettingsFeatureSimpleStateChecker());
var emailPermission = moduleGroup
.AddPermission(SettingManagementPermissions.Emailing, L("Permission:Emailing"));
emailPermission.StateCheckers.Add(new AllowTenantsToChangeEmailSettingsFeatureSimpleStateChecker());
emailPermission.AddChild(SettingManagementPermissions.EmailingTest, L("Permission:EmailingTest"));
}
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 Emailing = GroupName + ".Emailing";
public const string EmailingTest = Emailing + ".Test";
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
{
protected ISettingManager SettingManager { get; }
protected IEmailSender EmailSender { get; }
public EmailSettingsAppService(ISettingManager settingManager)
public EmailSettingsAppService(ISettingManager settingManager, IEmailSender emailSender)
{
SettingManager = settingManager;
EmailSender = emailSender;
}
public virtual async Task<EmailSettingsDto> GetAsync()
@ -60,6 +63,14 @@ public class EmailSettingsAppService : SettingManagementAppServiceBase, IEmailSe
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()
{
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>
<TextEdit @bind-Text="@EmailSettings.DefaultFromDisplayName">
<Feedback>
<ValidationError />
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
@ -23,17 +23,17 @@
<FieldLabel>@L["DefaultFromAddress"] *</FieldLabel>
<TextEdit @bind-Text="@EmailSettings.DefaultFromAddress">
<Feedback>
<ValidationError />
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["SmtpHost"]</FieldLabel>
<FieldLabel>@L["SmtpHost"]</FieldLabel>
<TextEdit @bind-Text="@EmailSettings.SmtpHost">
<Feedback>
<ValidationError />
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
@ -58,30 +58,30 @@
{
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["SmtpDomain"]</FieldLabel>
<FieldLabel>@L["SmtpDomain"]</FieldLabel>
<TextEdit @bind-Text="@EmailSettings.SmtpDomain">
<Feedback>
<ValidationError />
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["SmtpUserName"]</FieldLabel>
<FieldLabel>@L["SmtpUserName"]</FieldLabel>
<TextEdit @bind-Text="@EmailSettings.SmtpUserName">
<Feedback>
<ValidationError />
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
</Validation>
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["SmtpPassword"]</FieldLabel>
<FieldLabel>@L["SmtpPassword"]</FieldLabel>
<TextEdit Role="TextRole.Password" @bind-Text="@EmailSettings.SmtpPassword">
<Feedback>
<ValidationError />
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
@ -92,8 +92,75 @@
</Validations>
<Row>
<Column>
<SubmitButton Clicked="@UpdateSettingsAsync" />
<SubmitButton Clicked="@UpdateSettingsAsync"/>
@if (HasSendTestEmailPermission)
{
<Button style="margin: 0.25rem" Color="Color.Primary" Clicked="OpenSendTestEmailModalAsync">@L["SendTestEmail"]</Button>
}
</Column>
</Row>
</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.Web.Configuration;
using Volo.Abp.Auditing;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.SettingManagement.Localization;
namespace Volo.Abp.SettingManagement.Blazor.Pages.SettingManagement.EmailSettingGroup;
@ -14,6 +15,9 @@ public partial class EmailSettingGroupViewComponent
{
[Inject]
protected IEmailSettingsAppService EmailSettingsAppService { get; set; }
[Inject]
protected IPermissionChecker PermissionChecker { get; set; }
[Inject]
private ICurrentApplicationConfigurationCacheResetService CurrentApplicationConfigurationCacheResetService { get; set; }
@ -23,7 +27,17 @@ public partial class EmailSettingGroupViewComponent
protected UpdateEmailSettingsViewModel EmailSettings;
protected SendTestEmailViewModel SendTestEmailInput;
protected Validations EmailSettingValidation;
protected Validations EmailSettingTestValidation;
protected Modal SendTestEmailModal;
protected bool HasSendTestEmailPermission { get; set; }
public EmailSettingGroupViewComponent()
{
@ -36,6 +50,8 @@ public partial class EmailSettingGroupViewComponent
try
{
EmailSettings = ObjectMapper.Map<EmailSettingsDto, UpdateEmailSettingsViewModel>(await EmailSettingsAppService.GetAsync());
HasSendTestEmailPermission = await PermissionChecker.IsGrantedAsync(SettingManagementPermissions.EmailingTest);
SendTestEmailInput = new SendTestEmailViewModel();
}
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
{
[MaxLength(256)]
@ -104,4 +166,18 @@ public partial class EmailSettingGroupViewComponent
[Display(Name = "DefaultFromDisplayName")]
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<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",
"Permission:SettingManagement": "Setting Management",
"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",
"SmtpHost": "Host",
"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",
"Permission:SettingManagement": "Ayarlar yönetimi",
"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",
"SmtpHost": "Sunucu",
"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": "保存成功",
"Permission:SettingManagement": "设置管理",
"Permission:Emailing": "邮件",
"Permission:EmailingTest": "邮件测试",
"SendTestEmail": "发送测试邮件",
"SenderEmailAddress": "发件人邮箱地址",
"TargetEmailAddress": "收件人邮箱地址",
"Subject": "主题",
"Body": "正文",
"TestEmailSubject": "测试邮件 {0}",
"TestEmailBody": "测试邮件内容",
"SuccessfullySent": "发送成功",
"Send": "发送",
"Menu:Emailing": "邮件",
"SmtpHost": "主机",
"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": "保存成功",
"Permission:SettingManagement": "設定管理",
"Permission:Emailing": "信箱",
"Permission:EmailingTest": "邮件測試",
"SendTestEmail": "發送測試邮件",
"SenderEmailAddress": "發送者電子郵件地址",
"TargetEmailAddress": "目標電子郵件地址",
"Subject": "主題",
"Body": "體",
"TestEmailSubject": "測試邮件 {0}",
"TestEmailBody": "測試邮件內容",
"SuccessfullySent": "成功發送",
"Send": "發送",
"Menu:Emailing": "信箱",
"SmtpHost": "主機",
"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 }
});
}
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": {
"controllerName": "EmailSettings",
"controllerGroupName": "EmailSettings",
"isRemoteService": true,
"apiVersion": null,
"type": "Volo.Abp.SettingManagement.EmailSettingsController",
"interfaces": [
{
@ -65,6 +67,43 @@
},
"allowAnonymous": null,
"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);
}
[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 Volo.Abp.Authorization.Permissions
@using Volo.Abp.SettingManagement
@using Volo.Abp.SettingManagement.Localization
@inject IHtmlLocalizer<AbpSettingManagementResource> L
@inject IPermissionChecker PermissionChecker
@model Volo.Abp.SettingManagement.Web.Pages.SettingManagement.Components.EmailSettingGroup.EmailSettingGroupViewComponent.UpdateEmailSettingsViewModel
<form id="EmailSettingsForm" method="post">
@ -24,6 +27,12 @@
<abp-button button-type="Primary" type="submit">
<i class="fa fa-save"></i> @L["Save"]
</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>
</abp-column>
</abp-row>

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

@ -1,16 +1,20 @@
(function ($) {
var _sendTestEmailModal = new abp.ModalManager(
abp.appPath + 'SettingManagement/Components/EmailSettingGroup/SendTestEmailModal'
);
$(function () {
var l = abp.localization.getResource('AbpSettingManagement');
$("#EmailSettingsForm").on('submit', function (event) {
event.preventDefault();
if(!$(this).valid()) {
if (!$(this).valid()) {
return;
}
var form = $(this).serializeFormToObject();
volo.abp.settingManagement.emailSettings.update(form).then(function (result) {
$(document).trigger("AbpSettingSaved");
@ -21,11 +25,28 @@
$('#SmtpUseDefaultCredentials').change(function () {
if (this.checked) {
$('#HideSectionWhenUseDefaultCredentialsIsChecked').slideUp();
}
else {
} else {
$('#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);

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()
{
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));
};
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 Volo.Abp.Data;
using Volo.Abp.EventBus;
namespace Volo.Abp.Users;
[EventName("Volo.Abp.Users.User")]
public class UserEto : IUserData
public class UserEto : IUserData, IHasExtraProperties
{
public Guid Id { get; set; }
@ -23,4 +24,6 @@ public class UserEto : IUserData
public string PhoneNumber { 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": {
"@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": {
"@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": {
"@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": {
"@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",
"typescript": "~4.5.4"
}
}
}

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

@ -5,4 +5,4 @@
"dependencies": {
"@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": {
"@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": {
"@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": {
"@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",
"typescript": "~4.5.4"
}
}
}

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

@ -5,4 +5,4 @@
"dependencies": {
"@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": {
"@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": {
"@abp/aspnetcore.mvc.ui.theme.basic": "^5.3.0-rc.1"
}
}
}

Loading…
Cancel
Save