Browse Source

Merge branch 'master' of https://github.com/volosoft/abp

pull/926/head
Alper Ebicoglu 8 years ago
parent
commit
77b414967a
  1. 4
      abp_io/src/Volo.AbpWebSite.Web/Pages/Templates.cshtml
  2. 1
      abp_io/src/Volo.AbpWebSite.Web/Templates/MvcApplicationTemplate.cs
  3. 20
      abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/ProjectBuildContextExtensions.cs
  4. 17
      abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/ProjectBuildPipelineStep.cs
  5. 2
      abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/Steps/RemoveProjectFromSolutionStep.cs
  6. 8
      abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/Steps/SwitchEntityFrameworkCoreToMongoDbStep.cs
  7. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs
  8. 23
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs
  9. 9
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationFeatureConfigurationDto.cs
  10. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs
  11. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/AbpAspNetCoreMvcUiBootstrapModule.cs
  12. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/AbpAspNetCoreMvcUiThemeSharedModule.cs
  13. 17
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js
  14. 0
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Layout/IPageLayout.cs
  15. 19
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
  16. 1
      framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/AbpBackgroundWorkersModule.cs
  17. 23
      framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs
  18. 1
      framework/src/Volo.Abp.Ddd.Application/Volo.Abp.Ddd.Application.csproj
  19. 28
      framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs
  20. 2
      framework/src/Volo.Abp.Features/Volo/Abp/Features/EditionFeatureValueProvider.cs
  21. 5
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
  22. 50
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpDictionaryBasedStringLocalizer.cs
  23. 11
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationModule.cs
  24. 58
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerExtensions.cs
  25. 8
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/DefaultResource.cs
  26. 10
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/IStringLocalizerSupportsInheritance.cs
  27. 7
      framework/src/Volo.Abp.UI.Navigation/Volo.Abp.UI.Navigation.csproj
  28. 24
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/AbpUiNavigationModule.cs
  29. 13
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenu.cs
  30. 59
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuExtensions.cs
  31. 10
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs
  32. 46
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItemList.cs
  33. 34
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/DefaultMenuContributor.cs
  34. 13
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/DefaultMenuNames.cs
  35. 4
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/IHasMenuItems.cs
  36. 10
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/AbpUiNavigationResource.cs
  37. 6
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/en.json
  38. 6
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/tr.json
  39. 25
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs
  40. 6
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/StandardMenus.cs
  41. 1
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/AbpUiResource.cs
  42. 11
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json
  43. 11
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json
  44. 9
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json
  45. 3
      framework/src/Volo.Abp.UI/Volo.Abp.UI.csproj
  46. 4
      framework/src/Volo.Abp.UI/Volo/Abp/Ui/AbpUiModule.cs
  47. 6
      framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/TestFeatureStore.cs
  48. 134
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalization_Tests.cs
  49. 6
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/LocalizationTestResource.cs
  50. 3
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/en.json
  51. 23
      framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs
  52. 6
      modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs
  53. 14
      modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/zh-Hans.json
  54. 2
      modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs
  55. 9
      modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs
  56. 11
      modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs
  57. 3
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs
  58. 2
      modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs
  59. 10
      modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/zh-Hans.json
  60. 26
      modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/zh-Hans.json
  61. 15
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json
  62. 6
      modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/AbpIdentityApplicationContractsModule.cs
  63. 2
      modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IIdentityUserAppService.cs
  64. 2
      modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IProfileAppService.cs
  65. 11
      modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityErrorCodes.cs
  66. 1
      modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/en.json
  67. 1
      modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/tr.json
  68. 6
      modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/zh-Hans.json
  69. 17
      modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs
  70. 6
      modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/ProfileAppService.cs
  71. 10
      modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj
  72. 18
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDataSeeder.cs
  73. 2
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs
  74. 5
      modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityUserController.cs
  75. 10
      modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/ProfileController.cs
  76. 4
      modules/identity/src/Volo.Abp.Identity.Web/Navigation/AbpIdentityWebMainMenuContributor.cs
  77. 13
      modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/ChangePasswordModal.cshtml.cs
  78. 1
      modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml
  79. 1
      modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml
  80. 4
      modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/zh-Hans.json
  81. 25
      modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml
  82. 15
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/AbpSettingManagementWebModule.cs
  83. 10
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/AbpSettingManagementResource.cs
  84. 6
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/en.json
  85. 6
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/tr.json
  86. 6
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/zh-Hans.json
  87. 16
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Navigation/SettingManagementMainMenuContributor.cs
  88. 9
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Navigation/SettingManagementMenuNames.cs
  89. 37
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Index.cshtml
  90. 2
      modules/setting-management/src/Volo.Abp.SettingManagement.Web/Volo.Abp.SettingManagement.Web.csproj
  91. 4
      modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Navigation/AbpTenantManagementWebMainMenuContributor.cs
  92. 3
      modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/AbpUsersDbContextModelCreatingExtensions.cs
  93. 44
      samples/MicroserviceDemo/k8s/auth-server-deployment.yaml
  94. 15
      samples/MicroserviceDemo/k8s/auth-server-service.yaml
  95. 44
      samples/MicroserviceDemo/k8s/backend-admin-app-deployment.yaml
  96. 68
      samples/MicroserviceDemo/k8s/backend-admin-app-gateway-deployment.yaml
  97. 15
      samples/MicroserviceDemo/k8s/backend-admin-app-gateway-service.yaml
  98. 15
      samples/MicroserviceDemo/k8s/backend-admin-app-service.yaml
  99. 56
      samples/MicroserviceDemo/k8s/blogging-service-deployment.yaml
  100. 15
      samples/MicroserviceDemo/k8s/blogging-service-service.yaml

4
abp_io/src/Volo.AbpWebSite.Web/Pages/Templates.cshtml

@ -14,7 +14,7 @@
@using (Html.BeginForm(FormMethod.Post)) @using (Html.BeginForm(FormMethod.Post))
{ {
<div class="row border"> <div class="row border">
<div class="col p-5 "> <div class="col-lg-7 p-5 ">
<h2> <h2>
<span class="text-primary">Create</span> <span class="text-primary">Create</span>
<span class="text-success">New Project</span> <span class="text-success">New Project</span>
@ -64,7 +64,7 @@
</div> </div>
</div> </div>
<div class="col-md-5 bg-light p-5"> <div class="col-lg-5 bg-light p-5">
<h4>The Startup Project</h4> <h4>The Startup Project</h4>
<p>See <a href="/documents/abp/latest/Getting-Started-AspNetCore-MVC-Template" target="_blank">the documentation</a> to understand how to run the downloaded project.</p> <p>See <a href="/documents/abp/latest/Getting-Started-AspNetCore-MVC-Template" target="_blank">the documentation</a> to understand how to run the downloaded project.</p>

1
abp_io/src/Volo.AbpWebSite.Web/Templates/MvcApplicationTemplate.cs

@ -37,6 +37,7 @@ namespace Volo.AbpWebSite.Templates
if (context.Request.DatabaseProvider != DatabaseProvider.EntityFrameworkCore) if (context.Request.DatabaseProvider != DatabaseProvider.EntityFrameworkCore)
{ {
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.EntityFrameworkCore")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.EntityFrameworkCore"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Application.Tests", projectFolderPath: "test/MyCompanyName.MyProjectName.Application.Tests")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Application.Tests", projectFolderPath: "test/MyCompanyName.MyProjectName.Application.Tests"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Tests", projectFolderPath: "test/MyCompanyName.MyProjectName.Web.Tests")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Tests", projectFolderPath: "test/MyCompanyName.MyProjectName.Web.Tests"));
} }

20
abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/ProjectBuildContextExtensions.cs

@ -0,0 +1,20 @@
using System;
using System.Linq;
using Volo.Utils.SolutionTemplating.Files;
namespace Volo.Utils.SolutionTemplating.Building
{
public static class ProjectBuildContextExtensions
{
public static FileEntry GetFile(this ProjectBuildContext context, string filePath)
{
var file = context.Files.FirstOrDefault(f => f.Name == filePath);
if (file == null)
{
throw new ApplicationException("Could not find file: " + filePath);
}
return file;
}
}
}

17
abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/ProjectBuildPipelineStep.cs

@ -1,22 +1,7 @@
using System; namespace Volo.Utils.SolutionTemplating.Building
using System.Linq;
using Volo.Utils.SolutionTemplating.Files;
namespace Volo.Utils.SolutionTemplating.Building
{ {
public abstract class ProjectBuildPipelineStep public abstract class ProjectBuildPipelineStep
{ {
public abstract void Execute(ProjectBuildContext context); public abstract void Execute(ProjectBuildContext context);
protected FileEntry GetFile(ProjectBuildContext context, string filePath)
{
var file = context.Files.FirstOrDefault(f => f.Name == filePath);
if (file == null)
{
throw new ApplicationException("Could not find file: " + filePath);
}
return file;
}
} }
} }

2
abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/Steps/RemoveProjectFromSolutionStep.cs

@ -23,7 +23,7 @@ namespace Volo.Utils.SolutionTemplating.Building.Steps
public override void Execute(ProjectBuildContext context) public override void Execute(ProjectBuildContext context)
{ {
context.Files.RemoveAll(file => file.Name.StartsWith(_projectFolderPath)); context.Files.RemoveAll(file => file.Name.StartsWith(_projectFolderPath));
var solutionFile = GetFile(context, _solutionFilePath); var solutionFile = context.GetFile(_solutionFilePath);
solutionFile.NormalizeLineEndings(); solutionFile.NormalizeLineEndings();
solutionFile.SetLines(RemoveProject(solutionFile.GetLines().ToList())); solutionFile.SetLines(RemoveProject(solutionFile.GetLines().ToList()));
} }

8
abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/Steps/SwitchEntityFrameworkCoreToMongoDbStep.cs

@ -14,7 +14,7 @@ namespace Volo.Utils.SolutionTemplating.Building.Steps
private void ChangeProjectReference(ProjectBuildContext context) private void ChangeProjectReference(ProjectBuildContext context)
{ {
var file = GetFile(context, "/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj"); var file = context.GetFile("/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj");
file.NormalizeLineEndings(); file.NormalizeLineEndings();
@ -29,12 +29,12 @@ namespace Volo.Utils.SolutionTemplating.Building.Steps
} }
} }
throw new ApplicationException("Could not find the 'Default' connection string in appsettings.json file!"); throw new ApplicationException("Could not find the EntityFrameworkCore reference in the MyCompanyName.MyProjectName.Web.csproj!");
} }
private void ChangeWebModuleUsage(ProjectBuildContext context) private void ChangeWebModuleUsage(ProjectBuildContext context)
{ {
var file = GetFile(context, "/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs"); var file = context.GetFile("/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs");
file.NormalizeLineEndings(); file.NormalizeLineEndings();
@ -59,7 +59,7 @@ namespace Volo.Utils.SolutionTemplating.Building.Steps
private void ChangeConnectionString(ProjectBuildContext context) private void ChangeConnectionString(ProjectBuildContext context)
{ {
var file = GetFile(context, "/src/MyCompanyName.MyProjectName.Web/appsettings.json"); var file = context.GetFile("/src/MyCompanyName.MyProjectName.Web/appsettings.json");
file.NormalizeLineEndings(); file.NormalizeLineEndings();

4
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs

@ -1,6 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Features; using Volo.Abp.Features;

23
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs

@ -0,0 +1,23 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Mvc.Client
{
public class RemoteLanguageProvider : ILanguageProvider, ITransientDependency
{
protected ICachedApplicationConfigurationClient ConfigurationClient { get; }
public RemoteLanguageProvider(ICachedApplicationConfigurationClient configurationClient)
{
ConfigurationClient = configurationClient;
}
public async Task<IReadOnlyList<LanguageInfo>> GetLanguagesAsync()
{
var configuration = await ConfigurationClient.GetAsync();
return configuration.Localization.Languages;
}
}
}

9
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationFeatureConfigurationDto.cs

@ -1,9 +1,16 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{ {
[Serializable]
public class ApplicationFeatureConfigurationDto public class ApplicationFeatureConfigurationDto
{ {
public Dictionary<string, string> Values { get; set; } public Dictionary<string, string> Values { get; set; }
public ApplicationFeatureConfigurationDto()
{
Values = new Dictionary<string, string>();
}
} }
} }

5
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs

@ -1,16 +1,21 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{ {
[Serializable] [Serializable]
public class ApplicationLocalizationConfigurationDto public class ApplicationLocalizationConfigurationDto
{ {
//TODO: Rename to Texts?
public Dictionary<string, Dictionary<string, string>> Values { get; set; } public Dictionary<string, Dictionary<string, string>> Values { get; set; }
public List<LanguageInfo> Languages { get; set; }
public ApplicationLocalizationConfigurationDto() public ApplicationLocalizationConfigurationDto()
{ {
Values = new Dictionary<string, Dictionary<string, string>>(); Values = new Dictionary<string, Dictionary<string, string>>();
Languages = new List<LanguageInfo>();
} }
} }
} }

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/AbpAspNetCoreMvcUiBootstrapModule.cs

@ -1,5 +1,4 @@
using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/AbpAspNetCoreMvcUiThemeSharedModule.cs

@ -1,5 +1,4 @@
using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Packages; using Volo.Abp.AspNetCore.Mvc.UI.Packages;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling;

17
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js

@ -338,6 +338,23 @@
} }
} }
configuration.language = {
info: localize("PagerInfo"),
infoFiltered: localize("PagerInfoFiltered"),
infoEmpty: localize("PagerInfoEmpty"),
search: localize("PagerSearch"),
processing: localize("ProcessingWithThreeDot"),
loadingRecords: localize("LoadingWithThreeDot"),
lengthMenu: localize("PagerShowMenuEntries"),
emptyTable: localize("NoDataAvailableInDatatable"),
paginate: {
first: localize("PagerFirst"),
last: localize("PagerLast"),
previous: localize("PagerPrevious"),
next: localize("PagerNext")
}
};
configuration.dom = '<"dataTable_filters"f>rt<"row dataTable_footer"<"col-auto"l><"col-auto"i><"col"p>>'; configuration.dom = '<"dataTable_filters"f>rt<"row dataTable_footer"<"col-auto"l><"col-auto"i><"col"p>>';
return configuration; return configuration;

0
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Layout/ILayoutManager.cs → framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Layout/IPageLayout.cs

19
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs

@ -24,6 +24,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
private readonly ISettingProvider _settingProvider; private readonly ISettingProvider _settingProvider;
private readonly ISettingDefinitionManager _settingDefinitionManager; private readonly ISettingDefinitionManager _settingDefinitionManager;
private readonly IFeatureDefinitionManager _featureDefinitionManager; private readonly IFeatureDefinitionManager _featureDefinitionManager;
private readonly ILanguageProvider _languageProvider;
public AbpApplicationConfigurationAppService( public AbpApplicationConfigurationAppService(
IOptions<AbpLocalizationOptions> localizationOptions, IOptions<AbpLocalizationOptions> localizationOptions,
@ -33,7 +34,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
ICurrentUser currentUser, ICurrentUser currentUser,
ISettingProvider settingProvider, ISettingProvider settingProvider,
SettingDefinitionManager settingDefinitionManager, SettingDefinitionManager settingDefinitionManager,
IFeatureDefinitionManager featureDefinitionManager) IFeatureDefinitionManager featureDefinitionManager,
ILanguageProvider languageProvider)
{ {
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider; _abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider;
@ -42,6 +44,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
_settingProvider = settingProvider; _settingProvider = settingProvider;
_settingDefinitionManager = settingDefinitionManager; _settingDefinitionManager = settingDefinitionManager;
_featureDefinitionManager = featureDefinitionManager; _featureDefinitionManager = featureDefinitionManager;
_languageProvider = languageProvider;
_localizationOptions = localizationOptions.Value; _localizationOptions = localizationOptions.Value;
} }
@ -53,7 +56,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{ {
Auth = await GetAuthConfigAsync(), Auth = await GetAuthConfigAsync(),
Features = await GetFeaturesConfigAsync(), Features = await GetFeaturesConfigAsync(),
Localization = GetLocalizationConfig(), Localization = await GetLocalizationConfigAsync(),
CurrentUser = GetCurrentUser(), CurrentUser = GetCurrentUser(),
Setting = await GetSettingConfigAsync() Setting = await GetSettingConfigAsync()
}; };
@ -87,10 +90,12 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
return authConfig; return authConfig;
} }
protected virtual ApplicationLocalizationConfigurationDto GetLocalizationConfig() protected virtual async Task<ApplicationLocalizationConfigurationDto> GetLocalizationConfigAsync()
{ {
var localizationConfig = new ApplicationLocalizationConfigurationDto(); var localizationConfig = new ApplicationLocalizationConfigurationDto();
localizationConfig.Languages.AddRange(await _languageProvider.GetLanguagesAsync());
foreach (var resource in _localizationOptions.Resources.Values) foreach (var resource in _localizationOptions.Resources.Values)
{ {
var dictionary = new Dictionary<string, string>(); var dictionary = new Dictionary<string, string>();
@ -104,8 +109,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
dictionary[localizedString.Name] = localizedString.Value; dictionary[localizedString.Name] = localizedString.Value;
} }
var resourceName = LocalizationResourceNameAttribute.GetName(resource.ResourceType); localizationConfig.Values[resource.ResourceName] = dictionary;
localizationConfig.Values[resourceName] = dictionary;
} }
return localizationConfig; return localizationConfig;
@ -133,10 +137,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
protected virtual async Task<ApplicationFeatureConfigurationDto> GetFeaturesConfigAsync() protected virtual async Task<ApplicationFeatureConfigurationDto> GetFeaturesConfigAsync()
{ {
var result = new ApplicationFeatureConfigurationDto var result = new ApplicationFeatureConfigurationDto();
{
Values = new Dictionary<string, string>()
};
foreach (var featureDefinition in _featureDefinitionManager.GetAll()) foreach (var featureDefinition in _featureDefinitionManager.GetAll())
{ {

1
framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/AbpBackgroundWorkersModule.cs

@ -10,7 +10,6 @@ namespace Volo.Abp.BackgroundWorkers
)] )]
public class AbpBackgroundWorkersModule : AbpModule public class AbpBackgroundWorkersModule : AbpModule
{ {
public override void OnApplicationInitialization(ApplicationInitializationContext context) public override void OnApplicationInitialization(ApplicationInitializationContext context)
{ {
var options = context.ServiceProvider.GetRequiredService<IOptions<BackgroundWorkerOptions>>().Value; var options = context.ServiceProvider.GetRequiredService<IOptions<BackgroundWorkerOptions>>().Value;

23
framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs

@ -1,5 +1,4 @@
using System; using System;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Distributed;
@ -70,11 +69,12 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool) hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return null; return null;
} }
throw; throw;
} }
@ -94,11 +94,14 @@ namespace Volo.Abp.Caching
try try
{ {
cachedBytes = await Cache.GetAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token)); cachedBytes = await Cache.GetAsync(
NormalizeKey(key),
CancellationTokenProvider.FallbackToProvider(token)
);
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool)hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return null; return null;
@ -185,7 +188,7 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool) hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return; return;
@ -210,7 +213,7 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool)hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return; return;
@ -230,7 +233,7 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool) hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return; return;
@ -250,7 +253,7 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool)hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return; return;
@ -270,7 +273,7 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool) hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
} }
@ -289,7 +292,7 @@ namespace Volo.Abp.Caching
} }
catch (Exception ex) catch (Exception ex)
{ {
if ((bool)hideErrors) if (hideErrors == true)
{ {
Logger.LogException(ex, LogLevel.Warning); Logger.LogException(ex, LogLevel.Warning);
return; return;

1
framework/src/Volo.Abp.Ddd.Application/Volo.Abp.Ddd.Application.csproj

@ -19,6 +19,7 @@
<ProjectReference Include="..\Volo.Abp.Ddd.Domain\Volo.Abp.Ddd.Domain.csproj" /> <ProjectReference Include="..\Volo.Abp.Ddd.Domain\Volo.Abp.Ddd.Domain.csproj" />
<ProjectReference Include="..\Volo.Abp.Features\Volo.Abp.Features.csproj" /> <ProjectReference Include="..\Volo.Abp.Features\Volo.Abp.Features.csproj" />
<ProjectReference Include="..\Volo.Abp.Http.Abstractions\Volo.Abp.Http.Abstractions.csproj" /> <ProjectReference Include="..\Volo.Abp.Http.Abstractions\Volo.Abp.Http.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.Localization\Volo.Abp.Localization.csproj" />
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" /> <ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" /> <ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.csproj" /> <ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.csproj" />

28
framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs

@ -1,16 +1,18 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Aspects; using Volo.Abp.Aspects;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.Authorization; using Volo.Abp.Authorization;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Features; using Volo.Abp.Features;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping; using Volo.Abp.ObjectMapping;
using Volo.Abp.Settings; using Volo.Abp.Settings;
@ -21,8 +23,8 @@ using Volo.Abp.Validation;
namespace Volo.Abp.Application.Services namespace Volo.Abp.Application.Services
{ {
public abstract class ApplicationService : public abstract class ApplicationService :
IApplicationService, IApplicationService,
IAvoidDuplicateCrossCuttingConcerns, IAvoidDuplicateCrossCuttingConcerns,
IValidationEnabled, IValidationEnabled,
IUnitOfWorkEnabled, IUnitOfWorkEnabled,
@ -53,6 +55,22 @@ namespace Volo.Abp.Application.Services
public IFeatureChecker FeatureChecker { get; set; } public IFeatureChecker FeatureChecker { get; set; }
public IStringLocalizerFactory StringLocalizerFactory { get; set; }
public IStringLocalizer L => _localizer ?? (_localizer = StringLocalizerFactory.Create(LocalizationResource));
private IStringLocalizer _localizer;
protected Type LocalizationResource
{
get => _localizationResource;
set
{
_localizationResource = value;
_localizer = null;
}
}
private Type _localizationResource = typeof(DefaultResource);
protected IUnitOfWork CurrentUnitOfWork => UnitOfWorkManager?.Current; protected IUnitOfWork CurrentUnitOfWork => UnitOfWorkManager?.Current;
protected ILogger Logger => _lazyLogger.Value; protected ILogger Logger => _lazyLogger.Value;

2
framework/src/Volo.Abp.Features/Volo/Abp/Features/EditionFeatureValueProvider.cs

@ -20,7 +20,7 @@ namespace Volo.Abp.Features
public override async Task<string> GetOrNullAsync(FeatureDefinition feature) public override async Task<string> GetOrNullAsync(FeatureDefinition feature)
{ {
var editionId = PrincipalAccessor.Principal.FindEditionId(); var editionId = PrincipalAccessor.Principal?.FindEditionId();
if (editionId == null) if (editionId == null)
{ {
return null; return null;

5
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs

@ -1,7 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -210,6 +212,9 @@ namespace Volo.Abp.Http.Client.DynamicProxying
//CorrelationId //CorrelationId
requestMessage.Headers.Add(CorrelationIdOptions.HttpHeaderName, CorrelationIdProvider.Get()); requestMessage.Headers.Add(CorrelationIdOptions.HttpHeaderName, CorrelationIdProvider.Get());
//TODO: Is that the way we want? Couldn't send the culture (not ui culture)
requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(CultureInfo.CurrentUICulture.Name));
} }
private string GetConfiguredApiVersion() private string GetConfiguredApiVersion()

50
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpDictionaryBasedStringLocalizer.cs

@ -8,7 +8,7 @@ using Microsoft.Extensions.Localization;
namespace Volo.Abp.Localization namespace Volo.Abp.Localization
{ {
public class AbpDictionaryBasedStringLocalizer : IStringLocalizer public class AbpDictionaryBasedStringLocalizer : IStringLocalizer, IStringLocalizerSupportsInheritance
{ {
public LocalizationResource Resource { get; } public LocalizationResource Resource { get; }
@ -26,7 +26,20 @@ namespace Volo.Abp.Localization
public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures) public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures)
{ {
return GetAllStrings(CultureInfo.CurrentUICulture.Name, includeParentCultures); return GetAllStrings(
CultureInfo.CurrentUICulture.Name,
includeParentCultures
);
}
public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures, bool includeBaseLocalizers)
{
return GetAllStrings(
CultureInfo.CurrentUICulture.Name,
includeParentCultures,
includeBaseLocalizers
);
} }
public IStringLocalizer WithCulture(CultureInfo culture) public IStringLocalizer WithCulture(CultureInfo culture)
@ -109,26 +122,32 @@ namespace Volo.Abp.Localization
return null; return null;
} }
protected virtual IReadOnlyList<LocalizedString> GetAllStrings(string cultureName, bool includeParentCultures = true) protected virtual IReadOnlyList<LocalizedString> GetAllStrings(
string cultureName,
bool includeParentCultures = true,
bool includeBaseLocalizers = true)
{ {
//TODO: Can be optimized (example: if it's already default dictionary, skip overriding) //TODO: Can be optimized (example: if it's already default dictionary, skip overriding)
var allStrings = new Dictionary<string, LocalizedString>(); var allStrings = new Dictionary<string, LocalizedString>();
foreach (var baseLocalizer in BaseLocalizers.Select(l => l.WithCulture(CultureInfo.GetCultureInfo(cultureName)))) if (includeBaseLocalizers)
{ {
//TODO: Try/catch is a workaround here! foreach (var baseLocalizer in BaseLocalizers.Select(l => l.WithCulture(CultureInfo.GetCultureInfo(cultureName))))
try
{ {
var baseLocalizedString = baseLocalizer.GetAllStrings(includeParentCultures); //TODO: Try/catch is a workaround here!
foreach (var localizedString in baseLocalizedString) try
{ {
allStrings[localizedString.Name] = localizedString; var baseLocalizedString = baseLocalizer.GetAllStrings(includeParentCultures);
foreach (var localizedString in baseLocalizedString)
{
allStrings[localizedString.Name] = localizedString;
}
} }
} catch (MissingManifestResourceException)
catch (MissingManifestResourceException) {
{
}
} }
} }
@ -160,7 +179,7 @@ namespace Volo.Abp.Localization
: cultureName; : cultureName;
} }
public class CultureWrapperStringLocalizer : IStringLocalizer public class CultureWrapperStringLocalizer : IStringLocalizer, IStringLocalizerSupportsInheritance
{ {
private readonly string _cultureName; private readonly string _cultureName;
private readonly AbpDictionaryBasedStringLocalizer _innerLocalizer; private readonly AbpDictionaryBasedStringLocalizer _innerLocalizer;
@ -184,6 +203,11 @@ namespace Volo.Abp.Localization
{ {
return new CultureWrapperStringLocalizer(culture.Name, _innerLocalizer); return new CultureWrapperStringLocalizer(culture.Name, _innerLocalizer);
} }
public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures, bool includeBaseLocalizers)
{
return _innerLocalizer.GetAllStrings(_cultureName, includeParentCultures, includeBaseLocalizers);
}
} }
} }
} }

11
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpLocalizationModule.cs

@ -23,9 +23,14 @@ namespace Volo.Abp.Localization
Configure<AbpLocalizationOptions>(options => Configure<AbpLocalizationOptions>(options =>
{ {
options.Resources options
.Add<AbpValidationResource>("en") .Resources
.AddVirtualJson("/Localization/Resources/AbpValidation"); .Add<DefaultResource>("en");
options
.Resources
.Add<AbpValidationResource>("en")
.AddVirtualJson("/Localization/Resources/AbpValidation");
}); });
} }
} }

58
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/AbpStringLocalizerExtensions.cs

@ -0,0 +1,58 @@
using System.Collections.Generic;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Extensions.Localization;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Reflection;
namespace Volo.Abp.Localization
{
public static class AbpStringLocalizerExtensions
{
[NotNull]
public static IStringLocalizer GetInternalLocalizer(
[NotNull] this IStringLocalizer stringLocalizer)
{
Check.NotNull(stringLocalizer, nameof(stringLocalizer));
var localizerType = stringLocalizer.GetType();
if (!ReflectionHelper.IsAssignableToGenericType(localizerType, typeof(StringLocalizer<>)))
{
return stringLocalizer;
}
var localizerField = localizerType
.GetField(
"_localizer",
BindingFlags.Instance |
BindingFlags.NonPublic
);
if (localizerField == null)
{
throw new AbpException($"Could not find the _localizer field inside the {typeof(StringLocalizer<>).FullName} class. Probably its name has changed. Please report this issue to the ABP framework.");
}
return localizerField.GetValue(stringLocalizer) as IStringLocalizer;
}
public static IEnumerable<LocalizedString> GetAllStrings(
this IStringLocalizer stringLocalizer,
bool includeParentCultures,
bool includeBaseLocalizers)
{
var internalLocalizer = (ProxyHelper.UnProxy(stringLocalizer) as IStringLocalizer).GetInternalLocalizer();
if (internalLocalizer is IStringLocalizerSupportsInheritance stringLocalizerSupportsInheritance)
{
return stringLocalizerSupportsInheritance.GetAllStrings(
includeParentCultures,
includeBaseLocalizers
);
}
return stringLocalizer.GetAllStrings(
includeParentCultures
);
}
}
}

8
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/DefaultResource.cs

@ -0,0 +1,8 @@
namespace Volo.Abp.Localization
{
[LocalizationResourceName("Default")]
public class DefaultResource
{
}
}

10
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/IStringLocalizerSupportsInheritance.cs

@ -0,0 +1,10 @@
using System.Collections.Generic;
using Microsoft.Extensions.Localization;
namespace Volo.Abp.Localization
{
public interface IStringLocalizerSupportsInheritance
{
IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures, bool includeBaseLocalizers);
}
}

7
framework/src/Volo.Abp.UI.Navigation/Volo.Abp.UI.Navigation.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
@ -13,6 +13,11 @@
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\Ui\Navigation\Localization\Resource\*.json" />
<Content Remove="Volo\Abp\Ui\Navigation\Localization\Resource\*.json" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.UI\Volo.Abp.UI.csproj" /> <ProjectReference Include="..\Volo.Abp.UI\Volo.Abp.UI.csproj" />
</ItemGroup> </ItemGroup>

24
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/AbpUiNavigationModule.cs

@ -1,10 +1,32 @@
using Volo.Abp.Modularity; using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Ui.Navigation;
using Volo.Abp.Ui.Navigation.Localization.Resource;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.UI.Navigation namespace Volo.Abp.UI.Navigation
{ {
[DependsOn(typeof(AbpUiModule))] [DependsOn(typeof(AbpUiModule))]
public class AbpUiNavigationModule : AbpModule public class AbpUiNavigationModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<VirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpUiNavigationModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<AbpUiNavigationResource>("en")
.AddVirtualJson("/Volo/Abp/Ui/Navigation/Localization/Resource");
});
Configure<NavigationOptions>(options =>
{
options.MenuContributors.Add(new DefaultMenuContributor());
});
}
} }
} }

13
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenu.cs

@ -1,5 +1,5 @@
using System.Collections.Generic;
using JetBrains.Annotations; using JetBrains.Annotations;
using Volo.Abp.Ui.Navigation;
namespace Volo.Abp.UI.Navigation namespace Volo.Abp.UI.Navigation
{ {
@ -29,11 +29,11 @@ namespace Volo.Abp.UI.Navigation
/// <inheritdoc cref="IHasMenuItems.Items"/> /// <inheritdoc cref="IHasMenuItems.Items"/>
[NotNull] [NotNull]
public IList<ApplicationMenuItem> Items { get; } //TODO: Create a specialized collection (that can contain AddAfter for example) public ApplicationMenuItemList Items { get; }
/// <summary> /// <summary>
/// Can be used to store a custom object related to this menu. /// Can be used to store a custom object related to this menu.
/// TODO: Conver to dictionary! /// TODO: Convert to dictionary!
/// </summary> /// </summary>
[CanBeNull] [CanBeNull]
public object CustomData { get; set; } public object CustomData { get; set; }
@ -47,7 +47,7 @@ namespace Volo.Abp.UI.Navigation
Name = name; Name = name;
DisplayName = displayName ?? Name; DisplayName = displayName ?? Name;
Items = new List<ApplicationMenuItem>(); Items = new ApplicationMenuItemList();
} }
/// <summary> /// <summary>
@ -60,5 +60,10 @@ namespace Volo.Abp.UI.Navigation
Items.Add(menuItem); Items.Add(menuItem);
return this; return this;
} }
public override string ToString()
{
return $"[ApplicationMenu] Name = {Name}";
}
} }
} }

59
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuExtensions.cs

@ -0,0 +1,59 @@
using JetBrains.Annotations;
using System.Linq;
using Volo.Abp.Ui.Navigation;
namespace Volo.Abp.UI.Navigation
{
public static class ApplicationMenuExtensions
{
[NotNull]
public static ApplicationMenuItem GetAdministration(
[NotNull] this ApplicationMenu applicationMenu)
{
return applicationMenu.GetMenuItem(
DefaultMenuNames.Application.Main.Administration
);
}
[NotNull]
public static ApplicationMenuItem GetMenuItem(
[NotNull] this IHasMenuItems menuWithItems,
string menuItemName)
{
var menuItem = menuWithItems.GetMenuItemOrNull(menuItemName);
if (menuItem == null)
{
throw new AbpException($"Could not find a menu item with given name: {menuItemName}");
}
return menuItem;
}
[CanBeNull]
public static ApplicationMenuItem GetMenuItemOrNull(
[NotNull] this IHasMenuItems menuWithItems,
string menuItemName)
{
Check.NotNull(menuWithItems, nameof(menuWithItems));
return menuWithItems.Items.FirstOrDefault(mi => mi.Name == menuItemName);
}
[NotNull]
public static IHasMenuItems SetSubItemOrder(
[NotNull] this IHasMenuItems menuWithItems,
string menuItemName,
int order)
{
Check.NotNull(menuWithItems, nameof(menuWithItems));
var menuItem = menuWithItems.GetMenuItemOrNull(menuItemName);
if (menuItem != null)
{
menuItem.Order = order;
}
return menuWithItems;
}
}
}

10
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using JetBrains.Annotations; using JetBrains.Annotations;
using Volo.Abp.Ui.Navigation;
namespace Volo.Abp.UI.Navigation namespace Volo.Abp.UI.Navigation
{ {
@ -68,7 +69,7 @@ namespace Volo.Abp.UI.Navigation
/// <inheritdoc cref="IHasMenuItems.Items"/> /// <inheritdoc cref="IHasMenuItems.Items"/>
[NotNull] [NotNull]
public IList<ApplicationMenuItem> Items { get; } public ApplicationMenuItemList Items { get; }
/// <summary> /// <summary>
/// Can be used to store a custom object related to this menu item. Optional. /// Can be used to store a custom object related to this menu item. Optional.
@ -109,7 +110,7 @@ namespace Volo.Abp.UI.Navigation
ElementId = elementId ?? GetDefaultElementId(); ElementId = elementId ?? GetDefaultElementId();
CssClass = cssClass; CssClass = cssClass;
Items = new List<ApplicationMenuItem>(); Items = new ApplicationMenuItemList();
} }
/// <summary> /// <summary>
@ -127,5 +128,10 @@ namespace Volo.Abp.UI.Navigation
{ {
return "MenuItem_" + Name; return "MenuItem_" + Name;
} }
public override string ToString()
{
return $"[ApplicationMenuItem] Name = {Name}";
}
} }
} }

46
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItemList.cs

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.Ui.Navigation
{
public class ApplicationMenuItemList : List<ApplicationMenuItem>
{
public ApplicationMenuItemList()
{
}
public ApplicationMenuItemList(int capacity)
: base(capacity)
{
}
public ApplicationMenuItemList(IEnumerable<ApplicationMenuItem> collection)
: base(collection)
{
}
public void Normalize()
{
RemoveEmptyItems();
Order();
}
private void RemoveEmptyItems()
{
RemoveAll(item => item.IsLeaf && item.Url.IsNullOrEmpty());
}
private void Order()
{
//TODO: Is there any way that is more performant?
var orderedItems = this.OrderBy(item => item.Order).ToArray();
Clear();
AddRange(orderedItems);
}
}
}

34
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/DefaultMenuContributor.cs

@ -0,0 +1,34 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using System.Threading.Tasks;
using Volo.Abp.Ui.Navigation.Localization.Resource;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.Ui.Navigation
{
public class DefaultMenuContributor : IMenuContributor
{
public virtual Task ConfigureMenuAsync(MenuConfigurationContext context)
{
Configure(context);
return Task.CompletedTask;
}
protected virtual void Configure(MenuConfigurationContext context)
{
var l = context.ServiceProvider
.GetRequiredService<IStringLocalizer<AbpUiNavigationResource>>();
if (context.Menu.Name == StandardMenus.Main)
{
context.Menu.AddItem(
new ApplicationMenuItem(
DefaultMenuNames.Application.Main.Administration,
l["Menu:Administration"],
icon: "fa fa-wrench"
)
);
}
}
}
}

13
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/DefaultMenuNames.cs

@ -0,0 +1,13 @@
namespace Volo.Abp.Ui.Navigation
{
public static class DefaultMenuNames
{
public static class Application
{
public static class Main
{
public const string Administration = "Abp.Application.Main.Administration";
}
}
}
}

4
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/IHasMenuItems.cs

@ -1,4 +1,4 @@
using System.Collections.Generic; using Volo.Abp.Ui.Navigation;
namespace Volo.Abp.UI.Navigation namespace Volo.Abp.UI.Navigation
{ {
@ -7,6 +7,6 @@ namespace Volo.Abp.UI.Navigation
/// <summary> /// <summary>
/// Menu items. /// Menu items.
/// </summary> /// </summary>
IList<ApplicationMenuItem> Items { get; } ApplicationMenuItemList Items { get; }
} }
} }

10
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/AbpUiNavigationResource.cs

@ -0,0 +1,10 @@
using Volo.Abp.Localization;
namespace Volo.Abp.Ui.Navigation.Localization.Resource
{
[LocalizationResourceName("AbpUiNavigation")]
public class AbpUiNavigationResource
{
}
}

6
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/en.json

@ -0,0 +1,6 @@
{
"culture": "en",
"texts": {
"Menu:Administration": "Administration"
}
}

6
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/tr.json

@ -0,0 +1,6 @@
{
"culture": "tr",
"texts": {
"Menu:Administration": "Yönetim"
}
}

25
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs

@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -9,26 +9,26 @@ namespace Volo.Abp.UI.Navigation
{ {
public class MenuManager : IMenuManager, ITransientDependency public class MenuManager : IMenuManager, ITransientDependency
{ {
private readonly NavigationOptions _options; protected NavigationOptions Options { get; }
private readonly IServiceProvider _serviceProvider; protected IHybridServiceScopeFactory ServiceScopeFactory { get; }
public MenuManager( public MenuManager(
IOptions<NavigationOptions> options, IOptions<NavigationOptions> options,
IServiceProvider serviceProvider) IHybridServiceScopeFactory serviceScopeFactory)
{ {
_serviceProvider = serviceProvider; ServiceScopeFactory = serviceScopeFactory;
_options = options.Value; Options = options.Value;
} }
public async Task<ApplicationMenu> GetAsync(string name) public async Task<ApplicationMenu> GetAsync(string name)
{ {
var menu = new ApplicationMenu(name); var menu = new ApplicationMenu(name);
using (var scope = _serviceProvider.CreateScope()) using (var scope = ServiceScopeFactory.CreateScope())
{ {
var context = new MenuConfigurationContext(menu, scope.ServiceProvider); var context = new MenuConfigurationContext(menu, scope.ServiceProvider);
foreach (var contributor in _options.MenuContributors) foreach (var contributor in Options.MenuContributors)
{ {
await contributor.ConfigureMenuAsync(context); await contributor.ConfigureMenuAsync(context);
} }
@ -39,9 +39,14 @@ namespace Volo.Abp.UI.Navigation
return menu; return menu;
} }
protected virtual void NormalizeMenu(ApplicationMenu menu) protected virtual void NormalizeMenu(IHasMenuItems menuWithItems)
{ {
menu.Items.RemoveAll(item => item.IsLeaf && item.Url.IsNullOrEmpty()); foreach (var menuItem in menuWithItems.Items)
{
NormalizeMenu(menuItem);
}
menuWithItems.Items.Normalize();
} }
} }
} }

6
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/StandardMenus.cs

@ -2,6 +2,12 @@ namespace Volo.Abp.UI.Navigation
{ {
public static class StandardMenus public static class StandardMenus
{ {
/* TODO: Consider to create nested class like
* StandardMenus.Application.Main
* StandardMenus.Application.User
* StandardMenus.Application.Shortcut
*/
public const string Main = "Main"; public const string Main = "Main";
public const string User = "User"; public const string User = "User";
public const string Shortcut = "Shortcut"; public const string Shortcut = "Shortcut";

1
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/AbpUiResource.cs

@ -2,6 +2,7 @@
namespace Localization.Resources.AbpUi namespace Localization.Resources.AbpUi
{ {
//TODO: Move to the Volo.Abp.UI.Localization.Resource folder
[LocalizationResourceName("AbpUi")] [LocalizationResourceName("AbpUi")]
public class AbpUiResource public class AbpUiResource
{ {

11
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json

@ -25,14 +25,23 @@
"Delete": "Delete", "Delete": "Delete",
"Edit": "Edit", "Edit": "Edit",
"ProcessingWithThreeDot": "Processing...", "ProcessingWithThreeDot": "Processing...",
"LoadingWithThreeDot": "Loading...",
"Welcome": "Welcome",
"Login": "Login", "Login": "Login",
"Register": "Register", "Register": "Register",
"Logout": "Log out", "Logout": "Log out",
"Submit": "Submit", "Submit": "Submit",
"Back": "Back", "Back": "Back",
"PagerSearch": "Search",
"PagerNext": "Next", "PagerNext": "Next",
"PagerPrevious": "Previous", "PagerPrevious": "Previous",
"PagerInfo": "Showing {0} to {1} of {2} entries.", "PagerFirst": "First",
"PagerLast": "Last",
"PagerInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
"PagerInfoEmpty": "Showing 0 to 0 of 0 entries",
"PagerInfoFiltered": "(filtered from _MAX_ total entries)",
"NoDataAvailableInDatatable": "No data available in table",
"PagerShowMenuEntries": "Show _MENU_ entries",
"DatatableActionDropdownDefaultText": "Actions", "DatatableActionDropdownDefaultText": "Actions",
"ChangePassword": "Change password", "ChangePassword": "Change password",
"PersonalInfo": "My profile" "PersonalInfo": "My profile"

11
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json

@ -25,14 +25,23 @@
"Delete": "Sil", "Delete": "Sil",
"Edit": "Düzenle", "Edit": "Düzenle",
"ProcessingWithThreeDot": "İşleniyor...", "ProcessingWithThreeDot": "İşleniyor...",
"LoadingWithThreeDot": "Yükleniyor...",
"Welcome": "Hoşgeldiniz",
"Login": "Giriş", "Login": "Giriş",
"Register": "Kaydol", "Register": "Kaydol",
"Logout": "Çıkış", "Logout": "Çıkış",
"Submit": "Gönder", "Submit": "Gönder",
"Back": "Geri", "Back": "Geri",
"PagerSearch": "Ara",
"PagerNext": "Sonraki", "PagerNext": "Sonraki",
"PagerPrevious": "Önceki", "PagerPrevious": "Önceki",
"PagerInfo": "{2} kayıttan {0} ile {1} arası gösteriliyor.", "PagerFirst": "İlk",
"PagerLast": "Son",
"PagerInfo": "_TOTAL_ kayıttan _START_ ile _END_ arası gösteriliyor.",
"PagerInfoEmpty": "0 kayıttan 0 ile 0 arası gösteriliyor.",
"PagerInfoFiltered": "(_MAX_ kayıt arasından filtrelendi)",
"NoDataAvailableInDatatable": "Tabloda kayır mevcut değil.",
"PagerShowMenuEntries": "Sayfada _MENU_ kayıt göster.",
"DatatableActionDropdownDefaultText": "İşlemler", "DatatableActionDropdownDefaultText": "İşlemler",
"ChangePassword": "Şifre değiştir", "ChangePassword": "Şifre değiştir",
"PersonalInfo": "Profilim" "PersonalInfo": "Profilim"

9
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json

@ -25,14 +25,23 @@
"Delete": "删除", "Delete": "删除",
"Edit": "修改", "Edit": "修改",
"ProcessingWithThreeDot": "处理中...", "ProcessingWithThreeDot": "处理中...",
"LoadingWithThreeDot": "加载中...",
"Welcome": "欢迎",
"Login": "登录", "Login": "登录",
"Register": "注册", "Register": "注册",
"Logout": "注销", "Logout": "注销",
"Submit": "提交", "Submit": "提交",
"Back": "返回", "Back": "返回",
"PagerSearch": "搜索",
"PagerNext": "下一页", "PagerNext": "下一页",
"PagerPrevious": "上一页", "PagerPrevious": "上一页",
"PagerFirst": "首页",
"PagerLast": "尾页",
"PagerInfo": "显示 {0} 到 {1} 个 {2} 条目.", "PagerInfo": "显示 {0} 到 {1} 个 {2} 条目.",
"PagerInfoEmpty": "显示0个条目中的0到0",
"PagerInfoFiltered": "(从 _MAX_ 总条目中过滤掉)",
"NoDataAvailableInDatatable": "表中没有数据",
"PagerShowMenuEntries": "显示 _MENU_ 实体",
"DatatableActionDropdownDefaultText": "操作", "DatatableActionDropdownDefaultText": "操作",
"ChangePassword": "修改密码", "ChangePassword": "修改密码",
"PersonalInfo": "个人信息" "PersonalInfo": "个人信息"

3
framework/src/Volo.Abp.UI/Volo.Abp.UI.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
@ -15,6 +15,7 @@
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Localization\**\*.json" /> <EmbeddedResource Include="Localization\**\*.json" />
<Content Remove="Localization\**\*.json" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

4
framework/src/Volo.Abp.UI/Volo/Abp/Ui/AbpUiModule.cs

@ -20,7 +20,9 @@ namespace Volo.Abp.UI
Configure<AbpLocalizationOptions>(options => Configure<AbpLocalizationOptions>(options =>
{ {
options.Resources.Add<AbpUiResource>("en").AddVirtualJson("/Localization/Resources/AbpUi"); options.Resources
.Add<AbpUiResource>("en")
.AddVirtualJson("/Localization/Resources/AbpUi");
}); });
} }
} }

6
framework/test/Volo.Abp.Features.Tests/Volo/Abp/Features/TestFeatureStore.cs

@ -20,9 +20,9 @@ namespace Volo.Abp.Features
{ {
_settingRecords = new List<SettingRecord> _settingRecords = new List<SettingRecord>
{ {
new SettingRecord("BooleanTestFeature1", TenantFeatureValueProvider.ProviderName, Tenant1Id.ToString(), "true"), new SettingRecord("BooleanTestFeature1", TenantFeatureValueProvider.ProviderName, Tenant1Id.ToString("N"), "true"),
new SettingRecord("BooleanTestFeature2", TenantFeatureValueProvider.ProviderName, Tenant1Id.ToString(), "true"), new SettingRecord("BooleanTestFeature2", TenantFeatureValueProvider.ProviderName, Tenant1Id.ToString("N"), "true"),
new SettingRecord("IntegerTestFeature1", TenantFeatureValueProvider.ProviderName, Tenant2Id.ToString(), "34") new SettingRecord("IntegerTestFeature1", TenantFeatureValueProvider.ProviderName, Tenant2Id.ToString("N"), "34")
}; };
} }

134
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalization_Tests.cs

@ -1,4 +1,5 @@
using System.Globalization; using System.Globalization;
using System.Linq;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Shouldly; using Shouldly;
@ -14,10 +15,28 @@ namespace Volo.Abp.Localization
public class AbpLocalization_Tests : AbpIntegratedTest<AbpLocalization_Tests.TestModule> public class AbpLocalization_Tests : AbpIntegratedTest<AbpLocalization_Tests.TestModule>
{ {
private readonly IStringLocalizer<LocalizationTestResource> _localizer; private readonly IStringLocalizer<LocalizationTestResource> _localizer;
private readonly IStringLocalizerFactory _localizerFactory;
public AbpLocalization_Tests() public AbpLocalization_Tests()
{ {
_localizer = GetRequiredService<IStringLocalizer<LocalizationTestResource>>(); _localizer = GetRequiredService<IStringLocalizer<LocalizationTestResource>>();
_localizerFactory = GetRequiredService<IStringLocalizerFactory>();
}
[Fact]
public void AbpStringLocalizerExtensions_GetInternalLocalizer()
{
var internalLocalizer = _localizer.GetInternalLocalizer();
internalLocalizer.ShouldNotBeNull();
internalLocalizer.ShouldBeOfType<AbpDictionaryBasedStringLocalizer>();
}
[Fact]
public void AbpStringLocalizerExtensions_GetInternalLocalizer_Using_LocalizerFactory()
{
var internalLocalizer = _localizerFactory.Create(typeof(LocalizationTestResource)).GetInternalLocalizer();
internalLocalizer.ShouldNotBeNull();
internalLocalizer.ShouldBeOfType<AbpDictionaryBasedStringLocalizer>();
} }
[Fact] [Fact]
@ -104,6 +123,102 @@ namespace Volo.Abp.Localization
_localizer.WithCulture(CultureInfo.GetCultureInfo("tr"))["CarPlural"].Value.ShouldBe("Araba"); _localizer.WithCulture(CultureInfo.GetCultureInfo("tr"))["CarPlural"].Value.ShouldBe("Araba");
} }
[Fact]
public void GetAllStrings_With_Parents()
{
using (AbpCultureHelper.Use("tr"))
{
var localizedStrings = _localizer.GetAllStrings(true).ToList();
localizedStrings.ShouldContain(
ls => ls.Name == "FortyTwo" &&
ls.Value == "Forty Two" &&
ls.ResourceNotFound == false
);
localizedStrings.ShouldContain(
ls => ls.Name == "Universe" &&
ls.Value == "Evren" &&
ls.ResourceNotFound == false
);
}
}
[Fact]
public void GetAllStrings_Without_Parents()
{
using (AbpCultureHelper.Use("tr"))
{
var localizedStrings = _localizer.GetAllStrings(false).ToList();
localizedStrings.ShouldNotContain(
ls => ls.Name == "FortyTwo"
);
localizedStrings.ShouldContain(
ls => ls.Name == "Universe" &&
ls.Value == "Evren" &&
ls.ResourceNotFound == false
);
}
}
[Fact]
public void GetAllStrings_With_Inheritance()
{
using (AbpCultureHelper.Use("tr"))
{
var localizedStrings = _localizer
.GetAllStrings(true, includeBaseLocalizers: true)
.ToList();
localizedStrings.ShouldContain(
ls => ls.Name == "USA" &&
ls.Value == "Amerika Birleşik Devletleri" &&
ls.ResourceNotFound == false
);
localizedStrings.ShouldContain(
ls => ls.Name == "Universe" &&
ls.Value == "Evren" &&
ls.ResourceNotFound == false
);
localizedStrings.ShouldContain(
ls => ls.Name == "SeeYou" &&
ls.Value == "See you" &&
ls.ResourceNotFound == false
);
}
}
[Fact]
public void GetAllStrings_Without_Inheritance()
{
using (AbpCultureHelper.Use("tr"))
{
var localizedStrings = _localizer
.GetAllStrings(true, includeBaseLocalizers: false)
.ToList();
localizedStrings.ShouldNotContain(
ls => ls.Name == "USA"
);
localizedStrings.ShouldContain(
ls => ls.Name == "Universe" &&
ls.Value == "Evren" &&
ls.ResourceNotFound == false
);
localizedStrings.ShouldContain(
ls => ls.Name == "SeeYou" &&
ls.Value == "See you" &&
ls.ResourceNotFound == false
);
}
}
[DependsOn(typeof(AbpTestBaseModule))] [DependsOn(typeof(AbpTestBaseModule))]
[DependsOn(typeof(AbpLocalizationModule))] [DependsOn(typeof(AbpLocalizationModule))]
public class TestModule : AbpModule public class TestModule : AbpModule
@ -117,10 +232,21 @@ namespace Volo.Abp.Localization
Configure<AbpLocalizationOptions>(options => Configure<AbpLocalizationOptions>(options =>
{ {
options.Resources.Add<LocalizationTestValidationResource>("en").AddVirtualJson("/Volo/Abp/Localization/TestResources/Base/Validation"); options.Resources
options.Resources.Add<LocalizationTestCountryNamesResource>("en").AddVirtualJson("/Volo/Abp/Localization/TestResources/Base/CountryNames"); .Add<LocalizationTestValidationResource>("en")
options.Resources.Add<LocalizationTestResource>("en").AddVirtualJson("/Volo/Abp/Localization/TestResources/Source"); .AddVirtualJson("/Volo/Abp/Localization/TestResources/Base/Validation");
options.Resources.Get<LocalizationTestResource>().AddVirtualJson("/Volo/Abp/Localization/TestResources/SourceExt");
options.Resources
.Add<LocalizationTestCountryNamesResource>("en")
.AddVirtualJson("/Volo/Abp/Localization/TestResources/Base/CountryNames");
options.Resources
.Add<LocalizationTestResource>("en")
.AddVirtualJson("/Volo/Abp/Localization/TestResources/Source");
options.Resources
.Get<LocalizationTestResource>()
.AddVirtualJson("/Volo/Abp/Localization/TestResources/SourceExt");
}); });
} }
} }

6
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/LocalizationTestResource.cs

@ -3,8 +3,10 @@ using Volo.Abp.Localization.TestResources.Base.Validation;
namespace Volo.Abp.Localization.TestResources.Source namespace Volo.Abp.Localization.TestResources.Source
{ {
[InheritResource(typeof(LocalizationTestValidationResource))] [InheritResource(
[InheritResource(typeof(LocalizationTestCountryNamesResource))] typeof(LocalizationTestValidationResource),
typeof(LocalizationTestCountryNamesResource)
)]
public sealed class LocalizationTestResource public sealed class LocalizationTestResource
{ {

3
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/en.json

@ -5,6 +5,7 @@
"Car": "Car", "Car": "Car",
"CarPlural": "Cars", "CarPlural": "Cars",
"MaxLenghtErrorMessage": "This field's length can be maximum of '{0}' chars", "MaxLenghtErrorMessage": "This field's length can be maximum of '{0}' chars",
"Universe": "Universe" "Universe": "Universe",
"FortyTwo": "Forty Two"
} }
} }

23
framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs

@ -2,7 +2,7 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Shouldly; using Shouldly;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using System.Collections.Generic; using Volo.Abp.Ui.Navigation;
using Xunit; using Xunit;
namespace Volo.Abp.UI.Navigation namespace Volo.Abp.UI.Navigation
@ -25,10 +25,13 @@ namespace Volo.Abp.UI.Navigation
mainMenu.DisplayName.ShouldBe("Main Menu"); mainMenu.DisplayName.ShouldBe("Main Menu");
mainMenu.Items.Count.ShouldBe(2); mainMenu.Items.Count.ShouldBe(2);
mainMenu.Items[0].Name.ShouldBe("Dashboard"); mainMenu.Items[0].Name.ShouldBe("Dashboard");
mainMenu.Items[1].Name.ShouldBe("Administration"); mainMenu.Items[1].Name.ShouldBe(DefaultMenuNames.Application.Main.Administration);
mainMenu.Items[1].Items[0].Name.ShouldBe("Administration.UserManagement"); mainMenu.Items[1].Items[0].Name.ShouldBe("Administration.UserManagement");
mainMenu.Items[1].Items[1].Name.ShouldBe("Administration.RoleManagement"); mainMenu.Items[1].Items[1].Name.ShouldBe("Administration.RoleManagement");
mainMenu.Items[1].Items[2].Name.ShouldBe("Administration.DashboardSettings"); mainMenu.Items[1].Items[2].Name.ShouldBe("Administration.DashboardSettings");
mainMenu.Items[1].Items[3].Name.ShouldBe("Administration.SubMenu1");
mainMenu.Items[1].Items[3].Items[0].Name.ShouldBe("Administration.SubMenu1.1");
mainMenu.Items[1].Items[3].Items[1].Name.ShouldBe("Administration.SubMenu1.2");
} }
[DependsOn(typeof(AbpUiNavigationModule))] [DependsOn(typeof(AbpUiNavigationModule))]
@ -60,10 +63,7 @@ namespace Volo.Abp.UI.Navigation
context.Menu.DisplayName = "Main Menu"; context.Menu.DisplayName = "Main Menu";
var administration = context.Menu.Items.GetOrAdd( var administration = context.Menu.GetAdministration();
m => m.Name == "Administration",
() => new ApplicationMenuItem("Administration", "Administration")
);
administration.AddItem(new ApplicationMenuItem("Administration.UserManagement", "User Management", url: "/admin/users")); administration.AddItem(new ApplicationMenuItem("Administration.UserManagement", "User Management", url: "/admin/users"));
administration.AddItem(new ApplicationMenuItem("Administration.RoleManagement", "Role Management", url: "/admin/roles")); administration.AddItem(new ApplicationMenuItem("Administration.RoleManagement", "Role Management", url: "/admin/roles"));
@ -88,13 +88,16 @@ namespace Volo.Abp.UI.Navigation
context.Menu.Items.Insert(0, new ApplicationMenuItem("Dashboard", "Dashboard", url: "/dashboard")); context.Menu.Items.Insert(0, new ApplicationMenuItem("Dashboard", "Dashboard", url: "/dashboard"));
var administration = context.Menu.Items.GetOrAdd( var administration = context.Menu.GetAdministration();
m => m.Name == "Administration",
() => new ApplicationMenuItem("Administration", "Administration")
);
administration.AddItem(new ApplicationMenuItem("Administration.DashboardSettings", "Dashboard Settings", url: "/admin/settings/dashboard")); administration.AddItem(new ApplicationMenuItem("Administration.DashboardSettings", "Dashboard Settings", url: "/admin/settings/dashboard"));
administration.AddItem(
new ApplicationMenuItem("Administration.SubMenu1", "Sub menu 1")
.AddItem(new ApplicationMenuItem("Administration.SubMenu1.1", "Sub menu 1.1", url: "/submenu1/submenu1_1"))
.AddItem(new ApplicationMenuItem("Administration.SubMenu1.2", "Sub menu 1.2", url: "/submenu1/submenu1_2"))
);
return Task.CompletedTask; return Task.CompletedTask;
} }
} }

6
modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs

@ -47,6 +47,12 @@ namespace Volo.Abp.Account.Web.Areas.Account.Controllers
{ {
ValidateLoginInfo(login); ValidateLoginInfo(login);
var identityUser = await _userManager.FindByNameAsync(login.UserNameOrEmailAddress); var identityUser = await _userManager.FindByNameAsync(login.UserNameOrEmailAddress);
if (identityUser == null)
{
return new AbpLoginResult(LoginResultType.InvalidUserNameOrPassword);
}
return GetAbpLoginResult(await _signInManager.CheckPasswordSignInAsync(identityUser, login.Password, true)); return GetAbpLoginResult(await _signInManager.CheckPasswordSignInAsync(identityUser, login.Password, true));
} }

14
modules/account/src/Volo.Abp.Account.Web/Localization/Resources/AbpAccount/Web/zh-Hans.json

@ -11,12 +11,12 @@
"InvalidUserNameOrPassword": "用户名或密码错误!", "InvalidUserNameOrPassword": "用户名或密码错误!",
"LoginIsNotAllowed": "无法登录!你需要验证邮箱地址/手机号.", "LoginIsNotAllowed": "无法登录!你需要验证邮箱地址/手机号.",
"SelfRegistrationDisabledMessage": "应用程序未开放注册,请联系管理员添加新用户.", "SelfRegistrationDisabledMessage": "应用程序未开放注册,请联系管理员添加新用户.",
"Login": "Login", "Login": "登录",
"Cancel": "Cancel", "Cancel": "取消",
"Register": "Register", "Register": "注册",
"UseAnotherServiceToLogIn.": "Use another service to log in.", "UseAnotherServiceToLogIn.": "使用其他服务登录.",
"InvalidLoginRequest": "Invalid login request", "InvalidLoginRequest": "登录请求无效",
"ThereAreNoLoginSchemesConfiguredForThisClient": "There are no login schemes configured for this client.", "ThereAreNoLoginSchemesConfiguredForThisClient": "没有为此客户端配置登录方案.",
"LogInUsingYourProviderAccount": "Log in using your {0} account" "LogInUsingYourProviderAccount": "使用您的{0}帐户登录"
} }
} }

2
modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs

@ -20,6 +20,7 @@ namespace Volo.Abp.AuditLogging
string correlationId = null, string correlationId = null,
int? maxExecutionDuration = null, int? maxExecutionDuration = null,
int? minExecutionDuration = null, int? minExecutionDuration = null,
bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
@ -32,6 +33,7 @@ namespace Volo.Abp.AuditLogging
string correlationId = null, string correlationId = null,
int? maxExecutionDuration = null, int? maxExecutionDuration = null,
int? minExecutionDuration = null, int? minExecutionDuration = null,
bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
} }

9
modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs

@ -30,11 +30,12 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
string correlationId = null, string correlationId = null,
int? maxExecutionDuration = null, int? maxExecutionDuration = null,
int? minExecutionDuration = null, int? minExecutionDuration = null,
bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var query = GetListQuery(httpMethod, url, userName, applicationName, correlationId, maxExecutionDuration, minExecutionDuration, httpStatusCode, includeDetails); var query = GetListQuery(httpMethod, url, userName, applicationName, correlationId, maxExecutionDuration, minExecutionDuration, hasException, httpStatusCode, includeDetails);
var auditLogs = await query.OrderBy(sorting ?? "executionTime desc") var auditLogs = await query.OrderBy(sorting ?? "executionTime desc")
.PageBy(skipCount, maxResultCount) .PageBy(skipCount, maxResultCount)
@ -51,10 +52,11 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
string correlationId = null, string correlationId = null,
int? maxExecutionDuration = null, int? maxExecutionDuration = null,
int? minExecutionDuration = null, int? minExecutionDuration = null,
bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var query = GetListQuery(httpMethod, url, userName, applicationName, correlationId, maxExecutionDuration, minExecutionDuration, httpStatusCode); var query = GetListQuery(httpMethod, url, userName, applicationName, correlationId, maxExecutionDuration, minExecutionDuration, hasException, httpStatusCode);
var totalCount = await query.LongCountAsync(); var totalCount = await query.LongCountAsync();
@ -69,11 +71,14 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
string correlationId = null, string correlationId = null,
int? maxExecutionDuration = null, int? maxExecutionDuration = null,
int? minExecutionDuration = null, int? minExecutionDuration = null,
bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
bool includeDetails = false) bool includeDetails = false)
{ {
return DbSet.AsNoTracking() return DbSet.AsNoTracking()
.IncludeDetails(includeDetails) .IncludeDetails(includeDetails)
.WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions.Length > 0)
.WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null || auditLog.Exceptions.Length == 0)
.WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod != null && auditLog.HttpMethod.ToLowerInvariant() == httpMethod.ToLowerInvariant()) .WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod != null && auditLog.HttpMethod.ToLowerInvariant() == httpMethod.ToLowerInvariant())
.WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.ToLowerInvariant().Contains(url.ToLowerInvariant())) .WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.ToLowerInvariant().Contains(url.ToLowerInvariant()))
.WhereIf(userName != null, auditLog => auditLog.UserName != null && auditLog.UserName.ToLowerInvariant() == userName.ToLowerInvariant()) .WhereIf(userName != null, auditLog => auditLog.UserName != null && auditLog.UserName.ToLowerInvariant() == userName.ToLowerInvariant())

11
modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs

@ -31,11 +31,12 @@ namespace Volo.Abp.AuditLogging.MongoDB
string correlationId = null, string correlationId = null,
int? maxDuration = null, int? maxDuration = null,
int? minDuration = null, int? minDuration = null,
bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var query = GetListQuery(httpMethod, url, userName, applicationName, correlationId, maxDuration, minDuration, httpStatusCode, includeDetails); var query = GetListQuery(httpMethod, url, userName, applicationName, correlationId, maxDuration, minDuration, hasException, httpStatusCode, includeDetails);
return await query.OrderBy(sorting ?? "executionTime desc").As<IMongoQueryable<AuditLog>>() return await query.OrderBy(sorting ?? "executionTime desc").As<IMongoQueryable<AuditLog>>()
.PageBy<AuditLog, IMongoQueryable<AuditLog>>(skipCount, maxResultCount) .PageBy<AuditLog, IMongoQueryable<AuditLog>>(skipCount, maxResultCount)
@ -50,10 +51,11 @@ namespace Volo.Abp.AuditLogging.MongoDB
string correlationId = null, string correlationId = null,
int? maxDuration = null, int? maxDuration = null,
int? minDuration = null, int? minDuration = null,
bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var query = GetListQuery(httpMethod, url, userName, applicationName, correlationId, maxDuration, minDuration, httpStatusCode); var query = GetListQuery(httpMethod, url, userName, applicationName, correlationId, maxDuration, minDuration, hasException, httpStatusCode);
var count = await query.As<IMongoQueryable<AuditLog>>().LongCountAsync(); var count = await query.As<IMongoQueryable<AuditLog>>().LongCountAsync();
@ -68,10 +70,13 @@ namespace Volo.Abp.AuditLogging.MongoDB
string correlationId = null, string correlationId = null,
int? maxDuration = null, int? maxDuration = null,
int? minDuration = null, int? minDuration = null,
bool? hasException = null,
HttpStatusCode? httpStatusCode = null, HttpStatusCode? httpStatusCode = null,
bool includeDetails = false) bool includeDetails = false)
{ {
return GetMongoQueryable() return GetMongoQueryable()
.WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions.Length > 0)
.WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null || auditLog.Exceptions.Length == 0)
.WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod != null && auditLog.HttpMethod.ToLowerInvariant() == httpMethod.ToLowerInvariant()) .WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod != null && auditLog.HttpMethod.ToLowerInvariant() == httpMethod.ToLowerInvariant())
.WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.ToLowerInvariant().Contains(url.ToLowerInvariant())) .WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.ToLowerInvariant().Contains(url.ToLowerInvariant()))
.WhereIf(userName != null, auditLog => auditLog.UserName != null && auditLog.UserName.ToLowerInvariant() == userName.ToLowerInvariant()) .WhereIf(userName != null, auditLog => auditLog.UserName != null && auditLog.UserName.ToLowerInvariant() == userName.ToLowerInvariant())
@ -79,7 +84,7 @@ namespace Volo.Abp.AuditLogging.MongoDB
.WhereIf(correlationId != null, auditLog => auditLog.CorrelationId != null && auditLog.CorrelationId.ToLowerInvariant() == correlationId.ToLowerInvariant()) .WhereIf(correlationId != null, auditLog => auditLog.CorrelationId != null && auditLog.CorrelationId.ToLowerInvariant() == correlationId.ToLowerInvariant())
.WhereIf(httpStatusCode != null && httpStatusCode > 0, auditLog => auditLog.HttpStatusCode == (int?)httpStatusCode) .WhereIf(httpStatusCode != null && httpStatusCode > 0, auditLog => auditLog.HttpStatusCode == (int?)httpStatusCode)
.WhereIf(maxDuration != null && maxDuration > 0, auditLog => auditLog.ExecutionDuration <= maxDuration) .WhereIf(maxDuration != null && maxDuration > 0, auditLog => auditLog.ExecutionDuration <= maxDuration)
.WhereIf(minDuration != null && minDuration > 0, auditLog => auditLog.ExecutionDuration >= minDuration); ; .WhereIf(minDuration != null && minDuration > 0, auditLog => auditLog.ExecutionDuration >= minDuration);
} }
} }
} }

3
modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs

@ -228,8 +228,9 @@ namespace Volo.Blogging.Posts
{ {
tag.IncreaseUsageCount(); tag.IncreaseUsageCount();
tag = await _tagRepository.UpdateAsync(tag); tag = await _tagRepository.UpdateAsync(tag);
post.AddTag(tag.Id);
} }
post.AddTag(tag.Id);
} }
} }

2
modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs

@ -27,7 +27,7 @@ namespace Volo.Blogging.EntityFrameworkCore
{ {
b.ToTable(options.TablePrefix + "Users", options.Schema); b.ToTable(options.TablePrefix + "Users", options.Schema);
b.ConfigureAbpUser(options); b.ConfigureAbpUser();
b.ConfigureExtraProperties(); b.ConfigureExtraProperties();
}); });

10
modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/zh-Hans.json

@ -0,0 +1,10 @@
{
"culture": "zh-Hans",
"texts": {
"Permission:DocumentManagement": "文档管理",
"Permission:Projects": "项目",
"Permission:Edit": "编辑",
"Permission:Delete": "删除",
"Permission:Create": "创建"
}
}

26
modules/docs/src/Volo.Docs.Admin.Web/Localization/Resources/Docs/Web/zh-Hans.json

@ -0,0 +1,26 @@
{
"culture": "zh-Hans",
"texts": {
"Menu:DocumentManagement": "文档",
"Menu:ProjectManagement": "项目",
"CreateANewProject": "创建新项目",
"Edit": "编辑",
"Create": "创建",
"Projects": "项目",
"Name": "名称",
"ShortName": "简称",
"DocumentStoreType": "文件存储类型",
"Format": "格式",
"ShortNameInfoText": "将用于唯一的URL.",
"DisplayName:Name": "名称",
"DisplayName:ShortName": "简称",
"DisplayName:Format": "格式",
"DisplayName:DefaultDocumentName": "默认文档名称",
"DisplayName:NavigationDocumentName": "导航文档名称",
"DisplayName:MinimumVersion": "最低版本",
"DisplayName:MainWebsiteUrl": "主网站网址",
"DisplayName:LatestVersionBranchName": "最新版本的分支名称",
"DisplayName:GitHubRootUrl": "GitHub根网址",
"DisplayName:GitHubAccessToken": "GitHub访问令牌"
}
}

15
modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json

@ -2,14 +2,17 @@
"culture": "zh-Hans", "culture": "zh-Hans",
"texts": { "texts": {
"Documents": "文档", "Documents": "文档",
"BackToWebsite": "返回网站", "BackToWebsite": "返回主网站",
"Contributors": "贡献者",
"ShareOn": "分享到",
"Version": "版本", "Version": "版本",
"Edit": "编辑", "Edit": "编辑",
"InThisDocument": "在这个文档中", "Delete": "删除",
"GoToTop": "返回顶部", "InThisDocument": "在本文中",
"GoToTop": "到顶部",
"Projects": "项目", "Projects": "项目",
"NoProjectWarning": "当前并没有项目!", "NoProjectWarning": "还没有项目!",
"DocumentNotFound": "抱歉,您请求的文档不存在!", "DocumentNotFound": "找不到请求的文档!",
"NavigationDocumentNotFound": "此版本并没有导航文档!" "NavigationDocumentNotFound": "这个版本没有导航文件!"
} }
} }

6
modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/AbpIdentityApplicationContractsModule.cs

@ -7,6 +7,7 @@ using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement; using Volo.Abp.PermissionManagement;
using Volo.Abp.Users; using Volo.Abp.Users;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
using Volo.Abp.Localization.ExceptionHandling;
namespace Volo.Abp.Identity namespace Volo.Abp.Identity
{ {
@ -32,6 +33,11 @@ namespace Volo.Abp.Identity
.Get<IdentityResource>() .Get<IdentityResource>()
.AddVirtualJson("/Volo/Abp/Identity/Localization/ApplicationContracts"); .AddVirtualJson("/Volo/Abp/Identity/Localization/ApplicationContracts");
}); });
Configure<ExceptionLocalizationOptions>(options =>
{
options.MapCodeNamespace("Volo.Abp.Identity", typeof(IdentityResource));
});
} }
} }
} }

2
modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IIdentityUserAppService.cs

@ -14,7 +14,5 @@ namespace Volo.Abp.Identity
Task<IdentityUserDto> FindByUsernameAsync(string username); Task<IdentityUserDto> FindByUsernameAsync(string username);
Task<IdentityUserDto> FindByEmailAsync(string email); Task<IdentityUserDto> FindByEmailAsync(string email);
Task ChangePasswordAsync(string currentPassword, string newPassword);
} }
} }

2
modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IProfileAppService.cs

@ -8,5 +8,7 @@ namespace Volo.Abp.Identity
Task<ProfileDto> GetAsync(); Task<ProfileDto> GetAsync();
Task<ProfileDto> UpdateAsync(UpdateProfileDto input); Task<ProfileDto> UpdateAsync(UpdateProfileDto input);
Task ChangePasswordAsync(string currentPassword, string newPassword);
} }
} }

11
modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityErrorCodes.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Abp.Identity
{
public static class IdentityErrorCodes
{
public const string UserSelfDeletion = "Volo.Abp.Identity:010001";
}
}

1
modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/en.json

@ -1,6 +1,7 @@
{ {
"culture": "en", "culture": "en",
"texts": { "texts": {
"Volo.Abp.Identity:010001": "You can not delete your own account!",
"Permission:IdentityManagement": "Identity management", "Permission:IdentityManagement": "Identity management",
"Permission:RoleManagement": "Role management", "Permission:RoleManagement": "Role management",
"Permission:Create": "Create", "Permission:Create": "Create",

1
modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/tr.json

@ -1,6 +1,7 @@
{ {
"culture": "tr", "culture": "tr",
"texts": { "texts": {
"Volo.Abp.Identity:010001": "Kendi hesabınızı silemezsiniz!",
"Permission:IdentityManagement": "Kimlik yönetimi", "Permission:IdentityManagement": "Kimlik yönetimi",
"Permission:RoleManagement": "Rol yönetimi", "Permission:RoleManagement": "Rol yönetimi",
"Permission:Create": "Oluşturma", "Permission:Create": "Oluşturma",

6
modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/zh-Hans.json

@ -1,12 +1,14 @@
{ {
"culture": "zh-Hans", "culture": "zh-Hans",
"texts": { "texts": {
"Permission:IdentityManagement": "身份认证管理", "Volo.Abp.Identity:010001": "您无法删除自己的帐户!",
"Permission:IdentityManagement": "身份标识管理",
"Permission:RoleManagement": "角色管理", "Permission:RoleManagement": "角色管理",
"Permission:Create": "创建", "Permission:Create": "创建",
"Permission:Edit": "编辑", "Permission:Edit": "编辑",
"Permission:Delete": "删除", "Permission:Delete": "删除",
"Permission:ChangePermissions": "更改权限", "Permission:ChangePermissions": "更改权限",
"Permission:UserManagement": "用户管理" "Permission:UserManagement": "用户管理",
"Permission:UserLookup": "用户查询"
} }
} }

17
modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs

@ -80,6 +80,11 @@ namespace Volo.Abp.Identity
[Authorize(IdentityPermissions.Users.Delete)] [Authorize(IdentityPermissions.Users.Delete)]
public async Task DeleteAsync(Guid id) public async Task DeleteAsync(Guid id)
{ {
if (CurrentUser.Id == id)
{
throw new BusinessException(code: IdentityErrorCodes.UserSelfDeletion);
}
var user = await _userManager.FindByIdAsync(id.ToString()); var user = await _userManager.FindByIdAsync(id.ToString());
if (user == null) if (user == null)
{ {
@ -113,18 +118,6 @@ namespace Volo.Abp.Identity
); );
} }
//TODO: Move this to the profile service!
public async Task ChangePasswordAsync(string currentPassword, string newPassword)
{
if (!CurrentUser.Id.HasValue)
{
throw new AbpException("Current user Id is null!");
}
var currentUser = await _userManager.GetByIdAsync(CurrentUser.Id.Value);
(await _userManager.ChangePasswordAsync(currentUser, currentPassword, newPassword)).CheckErrors();
}
private async Task UpdateUserByInput(IdentityUser user, IdentityUserCreateOrUpdateDtoBase input) private async Task UpdateUserByInput(IdentityUser user, IdentityUserCreateOrUpdateDtoBase input)
{ {
(await _userManager.SetEmailAsync(user, input.Email)).CheckErrors(); (await _userManager.SetEmailAsync(user, input.Email)).CheckErrors();

6
modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/ProfileAppService.cs

@ -49,5 +49,11 @@ namespace Volo.Abp.Identity
return ObjectMapper.Map<IdentityUser, ProfileDto>(user); return ObjectMapper.Map<IdentityUser, ProfileDto>(user);
} }
public async Task ChangePasswordAsync(string currentPassword, string newPassword)
{
var currentUser = await _userManager.GetByIdAsync(CurrentUser.GetId());
(await _userManager.ChangePasswordAsync(currentUser, currentPassword, newPassword)).CheckErrors();
}
} }
} }

10
modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj

@ -17,6 +17,12 @@
<EmbeddedResource Include="Volo\Abp\Identity\Localization\Domain\*.json" /> <EmbeddedResource Include="Volo\Abp\Identity\Localization\Domain\*.json" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Compile Remove="Volo\Abp\Permissions\**" />
<EmbeddedResource Remove="Volo\Abp\Permissions\**" />
<None Remove="Volo\Abp\Permissions\**" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.Identity.Domain.Shared\Volo.Abp.Identity.Domain.Shared.csproj" /> <ProjectReference Include="..\Volo.Abp.Identity.Domain.Shared\Volo.Abp.Identity.Domain.Shared.csproj" />
@ -29,8 +35,4 @@
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Identity.Core" Version="2.2.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Volo\Abp\Permissions\" />
</ItemGroup>
</Project> </Project>

18
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDataSeeder.cs

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -53,7 +52,7 @@ namespace Volo.Abp.Identity
adminUser = new IdentityUser(_guidGenerator.Create(), adminUserName, "admin@abp.io", tenantId); adminUser = new IdentityUser(_guidGenerator.Create(), adminUserName, "admin@abp.io", tenantId);
adminUser.Name = adminUserName; adminUser.Name = adminUserName;
CheckIdentityErrors(await _userManager.CreateAsync(adminUser, adminUserPassword)); (await _userManager.CreateAsync(adminUser, adminUserPassword)).CheckErrors();
result.CreatedAdminUser = true; result.CreatedAdminUser = true;
//"admin" role //"admin" role
@ -65,24 +64,13 @@ namespace Volo.Abp.Identity
adminRole.IsStatic = true; adminRole.IsStatic = true;
adminRole.IsPublic = true; adminRole.IsPublic = true;
CheckIdentityErrors(await _roleManager.CreateAsync(adminRole)); (await _roleManager.CreateAsync(adminRole)).CheckErrors();
result.CreatedAdminRole = true; result.CreatedAdminRole = true;
} }
CheckIdentityErrors(await _userManager.AddToRoleAsync(adminUser, adminRoleName)); (await _userManager.AddToRoleAsync(adminUser, adminRoleName)).CheckErrors();
return result; return result;
} }
protected void CheckIdentityErrors(IdentityResult identityResult) //TODO: This is temporary and duplicate code!
{
if (!identityResult.Succeeded)
{
//TODO: A better exception that can be shown on UI as localized?
throw new AbpException("Operation failed: " + identityResult.Errors.Select(e => $"[{e.Code}] {e.Description}").JoinAsString(", "));
}
//identityResult.CheckErrors(LocalizationManager); //TODO: Get from old Abp
}
} }
} }

2
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs

@ -25,7 +25,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
b.ConfigureFullAudited(); b.ConfigureFullAudited();
b.ConfigureExtraProperties(); b.ConfigureExtraProperties();
b.ConfigureConcurrencyStamp(); b.ConfigureConcurrencyStamp();
b.ConfigureAbpUser(options); b.ConfigureAbpUser();
b.Property(u => u.NormalizedUserName).IsRequired().HasMaxLength(IdentityUserConsts.MaxNormalizedUserNameLength).HasColumnName(nameof(IdentityUser.NormalizedUserName)); b.Property(u => u.NormalizedUserName).IsRequired().HasMaxLength(IdentityUserConsts.MaxNormalizedUserNameLength).HasColumnName(nameof(IdentityUser.NormalizedUserName));
b.Property(u => u.NormalizedEmail).HasMaxLength(IdentityUserConsts.MaxNormalizedEmailLength).HasColumnName(nameof(IdentityUser.NormalizedEmail)); b.Property(u => u.NormalizedEmail).HasMaxLength(IdentityUserConsts.MaxNormalizedEmailLength).HasColumnName(nameof(IdentityUser.NormalizedEmail));

5
modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/IdentityUserController.cs

@ -64,10 +64,5 @@ namespace Volo.Abp.Identity
{ {
return _userAppService.FindByEmailAsync(email); return _userAppService.FindByEmailAsync(email);
} }
public Task ChangePasswordAsync(string currentPassword, string newPassword)
{
return _userAppService.ChangePasswordAsync(currentPassword, newPassword);
}
} }
} }

10
modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/ProfileController.cs

@ -1,7 +1,4 @@
using System; using System.Threading.Tasks;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc;
@ -27,5 +24,10 @@ namespace Volo.Abp.Identity
{ {
return _profileAppService.UpdateAsync(input); return _profileAppService.UpdateAsync(input);
} }
public Task ChangePasswordAsync(string currentPassword, string newPassword)
{
return _profileAppService.ChangePasswordAsync(currentPassword, newPassword);
}
} }
} }

4
modules/identity/src/Volo.Abp.Identity.Web/Navigation/AbpIdentityWebMainMenuContributor.cs

@ -16,11 +16,13 @@ namespace Volo.Abp.Identity.Web.Navigation
return; return;
} }
var administrationMenu = context.Menu.GetAdministration();
var authorizationService = context.ServiceProvider.GetRequiredService<IAuthorizationService>(); var authorizationService = context.ServiceProvider.GetRequiredService<IAuthorizationService>();
var l = context.ServiceProvider.GetRequiredService<IStringLocalizer<IdentityResource>>(); var l = context.ServiceProvider.GetRequiredService<IStringLocalizer<IdentityResource>>();
var identityMenuItem = new ApplicationMenuItem(IdentityMenuNames.GroupName, l["Menu:IdentityManagement"], icon: "fa fa-id-card-o"); var identityMenuItem = new ApplicationMenuItem(IdentityMenuNames.GroupName, l["Menu:IdentityManagement"], icon: "fa fa-id-card-o");
context.Menu.AddItem(identityMenuItem); administrationMenu.AddItem(identityMenuItem);
if (await authorizationService.IsGrantedAsync(IdentityPermissions.Roles.Default)) if (await authorizationService.IsGrantedAsync(IdentityPermissions.Roles.Default))
{ {

13
modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/ChangePasswordModal.cshtml.cs

@ -12,13 +12,14 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Shared
[BindProperty] [BindProperty]
public ChangePasswordInfoModel ChangePasswordInfoModel { get; set; } public ChangePasswordInfoModel ChangePasswordInfoModel { get; set; }
private readonly IIdentityUserAppService _userAppService; private readonly IProfileAppService _profileAppService;
private readonly IStringLocalizer<IdentityResource> _localizer; private readonly IStringLocalizer<IdentityResource> _localizer;
public ChangePasswordModal(IIdentityUserAppService userAppService, public ChangePasswordModal(
IProfileAppService profileAppService,
IStringLocalizer<IdentityResource> localizer) IStringLocalizer<IdentityResource> localizer)
{ {
_userAppService = userAppService; _profileAppService = profileAppService;
_localizer = localizer; _localizer = localizer;
} }
@ -31,8 +32,10 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Shared
throw new UserFriendlyException(_localizer.GetString("Identity.PasswordConfirmationFailed").Value); throw new UserFriendlyException(_localizer.GetString("Identity.PasswordConfirmationFailed").Value);
} }
await _userAppService.ChangePasswordAsync(ChangePasswordInfoModel.CurrentPassword, await _profileAppService.ChangePasswordAsync(
ChangePasswordInfoModel.NewPassword); ChangePasswordInfoModel.CurrentPassword,
ChangePasswordInfoModel.NewPassword
);
return NoContent(); return NoContent();
} }

1
modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml

@ -31,7 +31,6 @@
} }
</abp-tab> </abp-tab>
</abp-tabs> </abp-tabs>
<div asp-validation-summary="All"></div>
</abp-modal-body> </abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer> <abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal> </abp-modal>

1
modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml

@ -32,7 +32,6 @@
} }
</abp-tab> </abp-tab>
</abp-tabs> </abp-tabs>
<div asp-validation-summary="All"></div>
</abp-modal-body> </abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer> <abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal> </abp-modal>

4
modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/zh-Hans.json

@ -1,6 +1,8 @@
{ {
"culture": "zh-Hans", "culture": "zh-Hans",
"texts": { "texts": {
"Permissions": "权限" "Permissions": "权限",
"OnlyProviderPermissons": "只有这个提供商",
"All": "所有"
} }
} }

25
modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml

@ -14,23 +14,24 @@
<abp-modal-body> <abp-modal-body>
<input asp-for="@Model.ProviderKey" /> <input asp-for="@Model.ProviderKey" />
<input asp-for="@Model.ProviderName" /> <input asp-for="@Model.ProviderName" />
<abp-tabs tab-style="PillVertical" vertical-header-size="_4"> <abp-tabs name="PermissionsTabs" tab-style="PillVertical" vertical-header-size="_4">
@for (var i = 0; i < Model.Groups.Count; i++) @for (var i = 0; i < Model.Groups.Count; i++)
{ {
<abp-tab title="@Model.Groups[i].DisplayName" name="v-pills-tab-@Model.Groups[i].GetNormalizedGroupName()"> <abp-tab title="@Model.Groups[i].DisplayName" name="v-pills-tab-@Model.Groups[i].GetNormalizedGroupName()">
<h4>@Model.Groups[i].DisplayName</h4> <h4>@Model.Groups[i].DisplayName</h4>
<hr class="mt-3 mb-4" /> <hr class="mt-3 mb-4" />
<div class="pl-1 pt-1" style="height: 450px; overflow: auto;">
@for (var j = 0; j < Model.Groups[i].Permissions.Count; j++) @for (var j = 0; j < Model.Groups[i].Permissions.Count; j++)
{ {
<abp-input asp-for="@Model.Groups[i].Permissions[j].IsGranted" <abp-input asp-for="@Model.Groups[i].Permissions[j].IsGranted"
label="@Model.Groups[i].Permissions[j].GetShownName(Model.ProviderName)" label="@Model.Groups[i].Permissions[j].GetShownName(Model.ProviderName)"
disabled="@Model.Groups[i].Permissions[j].IsDisabled(Model.ProviderName)" disabled="@Model.Groups[i].Permissions[j].IsDisabled(Model.ProviderName)"
group-data-permission-name="@Model.Groups[i].Permissions[j].Name" group-data-permission-name="@Model.Groups[i].Permissions[j].Name"
group-data-parent-name="@(Model.Groups[i].Permissions[j].ParentName ?? "")" group-data-parent-name="@(Model.Groups[i].Permissions[j].ParentName ?? "")"
group-style="margin-left: @(Model.Groups[i].Permissions[j].Depth * 20)px" /> group-style="margin-left: @(Model.Groups[i].Permissions[j].Depth * 20)px" />
<input asp-for="@Model.Groups[i].Permissions[j].Name" /> <input asp-for="@Model.Groups[i].Permissions[j].Name" />
} }
</div>
</abp-tab> </abp-tab>
} }
</abp-tabs> </abp-tabs>

15
modules/setting-management/src/Volo.Abp.SettingManagement.Web/AbpSettingManagementWebModule.cs

@ -1,5 +1,7 @@
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.SettingManagement.Localization;
using Volo.Abp.SettingManagement.Web.Navigation; using Volo.Abp.SettingManagement.Web.Navigation;
using Volo.Abp.UI.Navigation; using Volo.Abp.UI.Navigation;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
@ -22,6 +24,19 @@ namespace Volo.Abp.SettingManagement.Web
{ {
options.FileSets.AddEmbedded<AbpSettingManagementWebModule>("Volo.Abp.SettingManagement.Web"); options.FileSets.AddEmbedded<AbpSettingManagementWebModule>("Volo.Abp.SettingManagement.Web");
}); });
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<AbpSettingManagementResource>("en");
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<AbpSettingManagementResource>()
.AddVirtualJson("/Localization/Resources/AbpSettingManagement");
});
} }
} }
} }

10
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/AbpSettingManagementResource.cs

@ -0,0 +1,10 @@
using Volo.Abp.Localization;
namespace Volo.Abp.SettingManagement.Localization
{
[LocalizationResourceName("AbpSettingManagement")]
public class AbpSettingManagementResource
{
}
}

6
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/en.json

@ -0,0 +1,6 @@
{
"culture": "en",
"texts": {
"Settings": "Settings"
}
}

6
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/tr.json

@ -0,0 +1,6 @@
{
"culture": "tr",
"texts": {
"Settings": "Ayarlar"
}
}

6
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/zh-Hans.json

@ -0,0 +1,6 @@
{
"culture": "zh-Hans",
"texts": {
"Settings": "设置"
}
}

16
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Navigation/SettingManagementMainMenuContributor.cs

@ -1,7 +1,9 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.SettingManagement.Localization;
using Volo.Abp.SettingManagement.Web.Pages.SettingManagement; using Volo.Abp.SettingManagement.Web.Pages.SettingManagement;
using Volo.Abp.UI.Navigation; using Volo.Abp.UI.Navigation;
@ -22,10 +24,18 @@ namespace Volo.Abp.SettingManagement.Web.Navigation
return Task.CompletedTask; return Task.CompletedTask;
} }
//TODO: Localize var l = context.ServiceProvider.GetRequiredService<IStringLocalizer<AbpSettingManagementResource>>();
//var l = context.ServiceProvider.GetRequiredService<IStringLocalizer<IdentityResource>>();
context.Menu.AddItem(new ApplicationMenuItem(SettingManagementMenuNames.GroupName, "Settings", "/SettingManagement", icon: "fa fa-cog", order: int.MaxValue - 1000)); context.Menu
.GetAdministration()
.AddItem(
new ApplicationMenuItem(
SettingManagementMenuNames.GroupName,
l["Settings"],
"/SettingManagement",
icon: "fa fa-cog"
)
);
return Task.CompletedTask; return Task.CompletedTask;
} }

9
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Navigation/SettingManagementMenuNames.cs

@ -1,14 +1,7 @@
using System; namespace Volo.Abp.SettingManagement.Web.Navigation
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Volo.Abp.SettingManagement.Web.Navigation
{ {
public class SettingManagementMenuNames public class SettingManagementMenuNames
{ {
public const string GroupName = "SettingManagement"; public const string GroupName = "SettingManagement";
public const string Settings = GroupName + ".Settings";
} }
} }

37
modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Index.cshtml

@ -1,11 +1,14 @@
@page @page
@using Volo.Abp.AspNetCore.Mvc.UI.Layout @using Volo.Abp.AspNetCore.Mvc.UI.Layout
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.SettingManagement.Localization
@using Volo.Abp.SettingManagement.Web.Navigation @using Volo.Abp.SettingManagement.Web.Navigation
@using Volo.Abp.SettingManagement.Web.Pages.SettingManagement @using Volo.Abp.SettingManagement.Web.Pages.SettingManagement
@model IndexModel @model IndexModel
@inject IHtmlLocalizer<AbpSettingManagementResource> L
@inject IPageLayout PageLayout @inject IPageLayout PageLayout
@{ @{
PageLayout.Content.Title = /*L["Settings"].Value*/ "Settings"; PageLayout.Content.Title = L["Settings"].Value;
PageLayout.Content.MenuItemName = SettingManagementMenuNames.GroupName; PageLayout.Content.MenuItemName = SettingManagementMenuNames.GroupName;
} }
@section scripts { @section scripts {
@ -14,21 +17,21 @@
</abp-script-bundle> </abp-script-bundle>
} }
<div id="SettingManagementWrapper"> <div id="SettingManagementWrapper">
<abp-card> <abp-card>
<abp-card-body> <abp-card-body>
<abp-tabs tab-style="PillVertical" vertical-header-size="_3"> <abp-tabs tab-style="PillVertical" vertical-header-size="_3">
@foreach (var group in Model.SettingPageCreationContext.Groups) @foreach (var group in Model.SettingPageCreationContext.Groups)
{ {
<abp-tab title="@group.DisplayName"> <abp-tab title="@group.DisplayName">
<h2>@group.DisplayName</h2> <h2>@group.DisplayName</h2>
<hr class="my-4" /> <hr class="my-4" />
@await Component.InvokeAsync(group.ComponentType) @await Component.InvokeAsync(group.ComponentType)
</abp-tab> </abp-tab>
} }
</abp-tabs> </abp-tabs>
</abp-card-body> </abp-card-body>
</abp-card> </abp-card>
</div> </div>

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

@ -14,6 +14,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj" /> <ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Localization\Volo.Abp.Localization.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -25,7 +26,6 @@
<Content Remove="Pages\**\*.cshtml" /> <Content Remove="Pages\**\*.cshtml" />
<Content Remove="Pages\**\*.js" /> <Content Remove="Pages\**\*.js" />
<Content Remove="Pages\**\*.css" /> <Content Remove="Pages\**\*.css" />
<Content Remove="Localization\Resources\**\*.json" />
<Content Remove="Properties\launchSettings.json" /> <Content Remove="Properties\launchSettings.json" />
<None Remove="Pages\Identity\Shared\personal-settings-modal.js" /> <None Remove="Pages\Identity\Shared\personal-settings-modal.js" />
<None Include="Properties\launchSettings.json" /> <None Include="Properties\launchSettings.json" />

4
modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Navigation/AbpTenantManagementWebMainMenuContributor.cs

@ -16,11 +16,13 @@ namespace Volo.Abp.TenantManagement.Web.Navigation
return; return;
} }
var administrationMenu = context.Menu.GetAdministration();
var authorizationService = context.ServiceProvider.GetRequiredService<IAuthorizationService>(); var authorizationService = context.ServiceProvider.GetRequiredService<IAuthorizationService>();
var l = context.ServiceProvider.GetRequiredService<IStringLocalizer<AbpTenantManagementResource>>(); var l = context.ServiceProvider.GetRequiredService<IStringLocalizer<AbpTenantManagementResource>>();
var tenantManagementMenuItem = new ApplicationMenuItem(TenantManagementMenuNames.GroupName, l["Menu:TenantManagement"], icon: "fa fa-users"); var tenantManagementMenuItem = new ApplicationMenuItem(TenantManagementMenuNames.GroupName, l["Menu:TenantManagement"], icon: "fa fa-users");
context.Menu.AddItem(tenantManagementMenuItem); administrationMenu.AddItem(tenantManagementMenuItem);
if (await authorizationService.IsGrantedAsync(TenantManagementPermissions.Tenants.Default)) if (await authorizationService.IsGrantedAsync(TenantManagementPermissions.Tenants.Default))
{ {

3
modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/AbpUsersDbContextModelCreatingExtensions.cs

@ -1,12 +1,11 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Volo.Abp.EntityFrameworkCore.Modeling;
namespace Volo.Abp.Users.EntityFrameworkCore namespace Volo.Abp.Users.EntityFrameworkCore
{ {
public static class AbpUsersDbContextModelCreatingExtensions public static class AbpUsersDbContextModelCreatingExtensions
{ {
public static void ConfigureAbpUser<TUser>(this EntityTypeBuilder<TUser> b, ModelBuilderConfigurationOptions options) public static void ConfigureAbpUser<TUser>(this EntityTypeBuilder<TUser> b)
where TUser : class, IUser where TUser : class, IUser
{ {
b.Property(u => u.TenantId).HasColumnName(nameof(IUser.TenantId)); b.Property(u => u.TenantId).HasColumnName(nameof(IUser.TenantId));

44
samples/MicroserviceDemo/k8s/auth-server-deployment.yaml

@ -1,33 +1,31 @@
apiVersion: extensions/v1beta1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
labels:
io.kompose.service: auth-server
name: auth-server name: auth-server
spec: spec:
selector:
matchLabels:
app: auth-server
replicas: 1 replicas: 1
strategy: {}
template: template:
metadata: metadata:
labels: labels:
io.kompose.service: auth-server app: auth-server
spec: spec:
containers: containers:
- env: - name: auth-server
- name: ASPNETCORE_ENVIRONMENT image: "volosoft/microservice-demo-auth-server"
value: Development env:
- name: ASPNETCORE_URLS - name: ASPNETCORE_ENVIRONMENT
value: http://0.0.0.0:51511 value: Development
- name: ConnectionStrings__Default - name: ASPNETCORE_URLS
value: Server=sqlserver;Database=MsDemo_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false value: http://0.0.0.0:51511
- name: RabbitMQ__Connections__Default__HostName - name: ConnectionStrings__Default
value: rabbitmq value: Server=sqlserver;Database=MsDemo_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false
- name: Redis__Configuration - name: RabbitMQ__Connections__Default__HostName
value: redis value: rabbitmq
image: volosoft/microservice-demo-auth-server - name: Redis__Configuration
name: auth-server value: redis
ports: ports:
- containerPort: 51511 - name: http
resources: {} containerPort: 51511
restartPolicy: Always
status: {}

15
samples/MicroserviceDemo/k8s/auth-server-service.yaml

@ -1,14 +1,11 @@
apiVersion: v1
kind: Service kind: Service
apiVersion: v1
metadata: metadata:
labels:
io.kompose.service: auth-server
name: auth-server name: auth-server
spec: spec:
ports:
- port: 51511
targetPort: 51511
selector: selector:
io.kompose.service: auth-server app: auth-server
status: ports:
loadBalancer: {} - protocol: TCP
port: 51511
targetPort: http

44
samples/MicroserviceDemo/k8s/backend-admin-app-deployment.yaml

@ -1,33 +1,31 @@
apiVersion: extensions/v1beta1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
labels:
io.kompose.service: backend-admin-app
name: backend-admin-app name: backend-admin-app
spec: spec:
selector:
matchLabels:
app: backend-admin-app
replicas: 1 replicas: 1
strategy: {}
template: template:
metadata: metadata:
labels: labels:
io.kompose.service: backend-admin-app app: backend-admin-app
spec: spec:
containers: containers:
- env: - name: backend-admin-app
- name: ASPNETCORE_ENVIRONMENT image: "volosoft/microservice-demo-backend-admin-app"
value: Development env:
- name: ASPNETCORE_URLS - name: ASPNETCORE_ENVIRONMENT
value: http://0.0.0.0:80 value: Development
- name: AuthServer__Authority - name: ASPNETCORE_URLS
value: http://auth-server:51511 value: http://0.0.0.0:80
- name: Redis__Configuration - name: AuthServer__Authority
value: redis value: http://auth-server:51511
- name: RemoteServices__Default__BaseUrl - name: Redis__Configuration
value: http://backend-admin-app-gateway/ value: redis
image: volosoft/microservice-demo-backend-admin-app - name: RemoteServices__Default__BaseUrl
name: backend-admin-app value: http://backend-admin-app-gateway/
ports: ports:
- containerPort: 80 - name: http
resources: {} containerPort: 80
restartPolicy: Always
status: {}

68
samples/MicroserviceDemo/k8s/backend-admin-app-gateway-deployment.yaml

@ -1,45 +1,43 @@
apiVersion: extensions/v1beta1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
labels:
io.kompose.service: backend-admin-app-gateway
name: backend-admin-app-gateway name: backend-admin-app-gateway
spec: spec:
selector:
matchLabels:
app: backend-admin-app-gateway
replicas: 1 replicas: 1
strategy: {}
template: template:
metadata: metadata:
labels: labels:
io.kompose.service: backend-admin-app-gateway app: backend-admin-app-gateway
spec: spec:
containers: containers:
- env: - name: backend-admin-app-gateway
- name: ASPNETCORE_ENVIRONMENT image: "volosoft/microservice-demo-backend-admin-app-gateway"
value: Development env:
- name: ASPNETCORE_URLS - name: ASPNETCORE_ENVIRONMENT
value: http://0.0.0.0:80 value: Development
- name: AuthServer__Authority - name: ASPNETCORE_URLS
value: http://auth-server:51511 value: http://0.0.0.0:80
- name: ConnectionStrings__Default - name: AuthServer__Authority
value: Server=sqlserver;Database=MsDemo_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false value: http://auth-server:51511
- name: GlobalConfiguration__BaseUrl - name: ConnectionStrings__Default
value: http://backend-admin-app-gateway value: Server=sqlserver;Database=MsDemo_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false
- name: ReRoutes__0__DownstreamHostAndPorts__0__Host - name: GlobalConfiguration__BaseUrl
value: identity-service value: http://backend-admin-app-gateway
- name: ReRoutes__0__DownstreamHostAndPorts__0__Port - name: ReRoutes__0__DownstreamHostAndPorts__0__Host
value: "80" value: identity-service
- name: ReRoutes__1__DownstreamHostAndPorts__0__Host - name: ReRoutes__0__DownstreamHostAndPorts__0__Port
value: product-service value: "80"
- name: ReRoutes__1__DownstreamHostAndPorts__0__Port - name: ReRoutes__1__DownstreamHostAndPorts__0__Host
value: "80" value: product-service
- name: Redis__Configuration - name: ReRoutes__1__DownstreamHostAndPorts__0__Port
value: redis value: "80"
- name: RemoteServices__Default__BaseUrl - name: Redis__Configuration
value: http://backend-admin-app-gateway/ value: redis
image: volosoft/microservice-demo-backend-admin-app-gateway - name: RemoteServices__Default__BaseUrl
name: backend-admin-app-gateway value: http://backend-admin-app-gateway/
ports: ports:
- containerPort: 80 - name: http
resources: {} containerPort: 80
restartPolicy: Always
status: {}

15
samples/MicroserviceDemo/k8s/backend-admin-app-gateway-service.yaml

@ -1,14 +1,11 @@
apiVersion: v1
kind: Service kind: Service
apiVersion: v1
metadata: metadata:
labels:
io.kompose.service: backend-admin-app-gateway
name: backend-admin-app-gateway name: backend-admin-app-gateway
spec: spec:
ports:
- port: 80
targetPort: 80
selector: selector:
io.kompose.service: backend-admin-app-gateway app: backend-admin-app-gateway
status: ports:
loadBalancer: {} - protocol: TCP
port: 80
targetPort: http

15
samples/MicroserviceDemo/k8s/backend-admin-app-service.yaml

@ -1,14 +1,11 @@
apiVersion: v1
kind: Service kind: Service
apiVersion: v1
metadata: metadata:
labels:
io.kompose.service: backend-admin-app
name: backend-admin-app name: backend-admin-app
spec: spec:
ports:
- port: 80
targetPort: 80
selector: selector:
io.kompose.service: backend-admin-app app: backend-admin-app
status: ports:
loadBalancer: {} - protocol: TCP
port: 80
targetPort: http

56
samples/MicroserviceDemo/k8s/blogging-service-deployment.yaml

@ -1,39 +1,37 @@
apiVersion: extensions/v1beta1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
labels:
io.kompose.service: blogging-service
name: blogging-service name: blogging-service
spec: spec:
selector:
matchLabels:
app: blogging-service
replicas: 1 replicas: 1
strategy: {}
template: template:
metadata: metadata:
labels: labels:
io.kompose.service: blogging-service app: blogging-service
spec: spec:
containers: containers:
- env: - name: blogging-service
- name: ASPNETCORE_ENVIRONMENT image: "volosoft/microservice-demo-blogging-service"
value: Development env:
- name: ASPNETCORE_URLS - name: ASPNETCORE_ENVIRONMENT
value: http://0.0.0.0:80 value: Development
- name: AuthServer__Authority - name: ASPNETCORE_URLS
value: http://auth-server:51511 value: http://0.0.0.0:80
- name: ConnectionStrings__Blogging - name: AuthServer__Authority
value: mongodb://mongodb|MsDemo_Blogging value: http://auth-server:51511
- name: ConnectionStrings__Default - name: ConnectionStrings__Blogging
value: Server=sqlserver;Database=MsDemo_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false value: mongodb://mongodb|MsDemo_Blogging
- name: RabbitMQ__Connections__Default__HostName - name: ConnectionStrings__Default
value: rabbitmq value: Server=sqlserver;Database=MsDemo_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false
- name: Redis__Configuration - name: RabbitMQ__Connections__Default__HostName
value: redis value: rabbitmq
- name: RemoteServices__Default__BaseUrl - name: Redis__Configuration
value: http://internal-gateway/ value: redis
image: volosoft/microservice-demo-blogging-service - name: RemoteServices__Default__BaseUrl
name: blogging-service value: http://internal-gateway/
ports: ports:
- containerPort: 80 - name: http
resources: {} containerPort: 80
restartPolicy: Always
status: {}

15
samples/MicroserviceDemo/k8s/blogging-service-service.yaml

@ -1,14 +1,11 @@
apiVersion: v1
kind: Service kind: Service
apiVersion: v1
metadata: metadata:
labels:
io.kompose.service: blogging-service
name: blogging-service name: blogging-service
spec: spec:
ports:
- port: 80
targetPort: 80
selector: selector:
io.kompose.service: blogging-service app: blogging-service
status: ports:
loadBalancer: {} - protocol: TCP
port: 80
targetPort: http

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save