diff --git a/docs/en/CLI.md b/docs/en/CLI.md index ff2daad528..8ea20ffd57 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -86,6 +86,8 @@ abp new Acme.BookStore * `--tiered`: Creates a tiered solution where Web and Http API layers are physically separated. If not specified, it creates a layered solution which is less complex and suitable for most scenarios. * `angular`: Angular. There are some additional options for this template: * `--separate-identity-server`: Separates the identity server application from the API host application. If not specified, you will have a single endpoint in the server side. + * `blazor`: Blazor. There are some additional options for this template: + * `--separate-identity-server`: Separates the identity server application from the API host application. If not specified, you will have a single endpoint in the server side. * `none`: Without UI. There are some additional options for this template: * `--separate-identity-server`: Separates the identity server application from the API host application. If not specified, you will have a single endpoint in the server side. * `--mobile` or `-m`: Specifies the mobile application framework. If not specified, no mobile application will be created. Available options: diff --git a/docs/zh-Hans/CLI.md b/docs/zh-Hans/CLI.md index 20afc1b50f..11f9964279 100644 --- a/docs/zh-Hans/CLI.md +++ b/docs/zh-Hans/CLI.md @@ -85,6 +85,8 @@ abp new Acme.BookStore * `--tiered`: 创建分层解决方案,Web和Http Api层在物理上是分开的.如果未指定会创建一个分层的解决方案,此解决方案没有那么复杂,适合大多数场景. * `angular`: Angular. 这个模板还有一些额外的选项: * `--separate-identity-server`: 将Identity Server应用程序与API host应用程序分开. 如果未指定,则服务器端将只有一个端点. + * `blazor`: Blazor. 这个模板还有一些额外的选项: + * `--separate-identity-server`: 将Identity Server应用程序与API host应用程序分开. 如果未指定,则服务器端将只有一个端点. * `none`: 无UI. 这个模板还有一些额外的选项: * `--separate-identity-server`: 将Identity Server应用程序与API host应用程序分开. 如果未指定,则服务器端将只有一个端点. * `--mobile` 或者 `-m`: 指定移动应用程序框架. 如果未指定,则不会创建任何移动应用程序,其他选项: diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor index 925783e16e..88a005d7bf 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor @@ -6,22 +6,36 @@ - - @CurrentUser.UserName - - - Logout - - + + @CurrentUser.UserName + + + @if (Menu != null) + { + @foreach (var menuItem in Menu.Items) + { + @menuItem.DisplayName + } + } + + Logout + + Log in @code{ + + private void NavigateTo(string uri) + { + Navigation.NavigateTo(uri); + } + private async Task BeginSignOut() { await SignOutManager.SetSignOutState(); - Navigation.NavigateTo("authentication/logout"); + NavigateTo("authentication/logout"); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs new file mode 100644 index 0000000000..e0ad688513 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Volo.Abp.UI.Navigation; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic +{ + public partial class LoginDisplay + { + [Inject] protected IMenuManager MenuManager { get; set; } + + protected ApplicationMenu Menu { get; set; } + + protected override async Task OnInitializedAsync() + { + Menu = await MenuManager.GetAsync(StandardMenus.User); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/IUiMessageService.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/IUiMessageService.cs index bad1bab7fc..2c834ddc87 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/IUiMessageService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/IUiMessageService.cs @@ -4,6 +4,14 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly { public interface IUiMessageService { + Task InfoAsync(string message, string title = null); + + Task SuccessAsync(string message, string title = null); + + Task WarnAsync(string message, string title = null); + + Task ErrorAsync(string message, string title = null); + Task ConfirmAsync(string message, string title = null); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/UiMessageService.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/UiMessageService.cs index 2e353b5e54..16fe041de4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/UiMessageService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/UiMessageService.cs @@ -4,6 +4,7 @@ using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Components.WebAssembly { + //TODO: Implement with sweetalert in a new package public class UiMessageService : IUiMessageService, ITransientDependency { protected IJSRuntime JsRuntime { get; } @@ -13,9 +14,28 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly JsRuntime = jsRuntime; } + public async Task InfoAsync(string message, string title = null) + { + await JsRuntime.InvokeVoidAsync("alert", message); + } + + public async Task SuccessAsync(string message, string title = null) + { + await JsRuntime.InvokeVoidAsync("alert", message); + } + + public async Task WarnAsync(string message, string title = null) + { + await JsRuntime.InvokeVoidAsync("alert", message); + } + + public async Task ErrorAsync(string message, string title = null) + { + await JsRuntime.InvokeVoidAsync("alert", message); + } + public async Task ConfirmAsync(string message, string title = null) { - //TODO: Implement with sweetalert in a new package return await JsRuntime.InvokeAsync("confirm", message); } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index d5ece4361f..39ecdb8183 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -286,6 +286,8 @@ namespace Volo.Abp.Cli.Commands return UiFramework.Mvc; case "angular": return UiFramework.Angular; + case "blazor": + return UiFramework.Blazor; default: return UiFramework.NotSpecified; } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs index 46d2b77f95..ad5da58a8e 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs @@ -19,13 +19,14 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building pipeline.Steps.Add(new TemplateCodeDeleteStep()); pipeline.Steps.Add(new SolutionRenameStep()); - if (context.Template.Name == AppProTemplate.TemplateName || + if (context.Template.Name == AppProTemplate.TemplateName || context.Template.Name == ModuleProTemplate.TemplateName) { pipeline.Steps.Add(new LicenseCodeReplaceStep()); } - if (context.BuildArgs.UiFramework == UiFramework.Mvc && context.BuildArgs.MobileApp == MobileApp.None) + if ((context.BuildArgs.UiFramework == UiFramework.Mvc || context.BuildArgs.UiFramework == UiFramework.Blazor) + && context.BuildArgs.MobileApp == MobileApp.None) { pipeline.Steps.Add(new RemoveRootFolderStep()); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs index 1ea2760b1c..17e33dc22d 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs @@ -5,6 +5,7 @@ NotSpecified = 0, None = 1, Mvc = 2, - Angular = 3 + Angular = 3, + Blazor = 4 } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFrameworkExtensions.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFrameworkExtensions.cs index 9161c9c63e..b247a8f424 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFrameworkExtensions.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFrameworkExtensions.cs @@ -9,9 +9,10 @@ case UiFramework.None: return "none"; case UiFramework.Mvc: return "mvc"; case UiFramework.Angular: return "angular"; + case UiFramework.Blazor: return "blazor"; case UiFramework.NotSpecified: return "NotSpecified"; default: return "NotSpecified"; } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs index 417c004f36..d309d4858a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs @@ -65,12 +65,22 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App ConfigureWithAngularUi(context, steps); break; + + case UiFramework.Blazor: + ConfigureWithBlazorUi(context, steps); + break; + case UiFramework.Mvc: case UiFramework.NotSpecified: ConfigureWithMvcUi(context, steps); break; } + if (context.BuildArgs.UiFramework != UiFramework.Blazor) + { + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor")); + } + if (context.BuildArgs.UiFramework != UiFramework.Angular) { steps.Add(new RemoveFolderStep("/angular")); @@ -101,6 +111,26 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App } } + private static void ConfigureWithBlazorUi(ProjectBuildContext context, List steps) + { + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Host")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Tests", projectFolderPath: "/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests")); + + if (context.BuildArgs.ExtraProperties.ContainsKey("separate-identity-server")) + { + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.HttpApi.HostWithIds")); + steps.Add(new BlazorAppsettingsFilePortChangeForSeparatedIdentityServersStep()); + } + else + { + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.HttpApi.Host")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.IdentityServer")); + steps.Add(new AppTemplateProjectRenameStep("MyCompanyName.MyProjectName.HttpApi.HostWithIds", "MyCompanyName.MyProjectName.HttpApi.Host")); + steps.Add(new AppTemplateChangeConsoleTestClientPortSettingsStep("44305")); + } + } + private static void ConfigureWithMvcUi(ProjectBuildContext context, List steps) { if (context.BuildArgs.ExtraProperties.ContainsKey("tiered")) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/BlazorAppsettingsFilePortChangeForSeparatedIdentityServersStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/BlazorAppsettingsFilePortChangeForSeparatedIdentityServersStep.cs new file mode 100644 index 0000000000..e83a630343 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/BlazorAppsettingsFilePortChangeForSeparatedIdentityServersStep.cs @@ -0,0 +1,39 @@ +using System; +using System.Linq; +using Volo.Abp.Cli.ProjectBuilding.Building; + +namespace Volo.Abp.Cli.ProjectBuilding.Templates.App +{ + public class BlazorAppsettingsFilePortChangeForSeparatedIdentityServersStep : ProjectBuildPipelineStep + { + public override void Execute(ProjectBuildContext context) + { + var appsettingsFile = context.Files.FirstOrDefault(x => + !x.IsDirectory && + x.Name.EndsWith("aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/appsettings.json", + StringComparison.InvariantCultureIgnoreCase) + ); + + appsettingsFile.NormalizeLineEndings(); + var lines = appsettingsFile.GetLines(); + + for (var i = 0; i < lines.Length; i++) + { + var line = lines[i]; + + if (line.Contains("Authority") && line.Contains("localhost")) + { + line = line.Replace("44305", "44301"); + } + else if (line.Contains("BaseUrl") && line.Contains("localhost")) + { + line = line.Replace("44305", "44300"); + } + + lines[i] = line; + } + + appsettingsFile.SetLines(lines); + } + } +} diff --git a/modules/account/Volo.Abp.Account.sln b/modules/account/Volo.Abp.Account.sln index c2b195f05b..b96627aac9 100644 --- a/modules/account/Volo.Abp.Account.sln +++ b/modules/account/Volo.Abp.Account.sln @@ -21,6 +21,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{12FAE513-7 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Account.Application.Tests", "test\Volo.Abp.Account.Application.Tests\Volo.Abp.Account.Application.Tests.csproj", "{356EAC51-5D55-4852-A8A5-2F90EAC8DAE3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Account.Blazor", "src\Volo.Abp.Account.Blazor\Volo.Abp.Account.Blazor.csproj", "{EE8858B3-A638-481B-8EB9-74F5E7D43D80}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -55,6 +57,10 @@ Global {356EAC51-5D55-4852-A8A5-2F90EAC8DAE3}.Debug|Any CPU.Build.0 = Debug|Any CPU {356EAC51-5D55-4852-A8A5-2F90EAC8DAE3}.Release|Any CPU.ActiveCfg = Release|Any CPU {356EAC51-5D55-4852-A8A5-2F90EAC8DAE3}.Release|Any CPU.Build.0 = Release|Any CPU + {EE8858B3-A638-481B-8EB9-74F5E7D43D80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE8858B3-A638-481B-8EB9-74F5E7D43D80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE8858B3-A638-481B-8EB9-74F5E7D43D80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE8858B3-A638-481B-8EB9-74F5E7D43D80}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -67,6 +73,7 @@ Global {EBF0C2B3-14CB-4DFC-9753-ECBF959CBA2E} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E} {7BCA5955-B3F6-41E8-9D5D-D115195C6098} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E} {356EAC51-5D55-4852-A8A5-2F90EAC8DAE3} = {12FAE513-7575-4235-89DF-277BA1A3B098} + {EE8858B3-A638-481B-8EB9-74F5E7D43D80} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2B054393-D2B2-4EA8-8A15-D60CBCF3E7A9} diff --git a/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorAutoMapperProfile.cs b/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorAutoMapperProfile.cs new file mode 100644 index 0000000000..f5c4cdc01d --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorAutoMapperProfile.cs @@ -0,0 +1,20 @@ +using AutoMapper; +using Volo.Abp.Account.Blazor.Pages.Account; +using Volo.Abp.AutoMapper; +using Volo.Abp.Identity; + +namespace Volo.Abp.Account.Blazor +{ + public class AbpAccountBlazorAutoMapperProfile : Profile + { + public AbpAccountBlazorAutoMapperProfile() + { + CreateMap() + .Ignore(x => x.PhoneNumberConfirmed) + .Ignore(x => x.EmailConfirmed); + + CreateMap() + .Ignore(x => x.ExtraProperties); + } + } +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorModule.cs b/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorModule.cs new file mode 100644 index 0000000000..c0917dd8f7 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorModule.cs @@ -0,0 +1,37 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AspNetCore.Components.WebAssembly.Theming; +using Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing; +using Volo.Abp.AutoMapper; +using Volo.Abp.Modularity; +using Volo.Abp.UI.Navigation; + +namespace Volo.Abp.Account.Blazor +{ + [DependsOn( + typeof(AbpAspNetCoreComponentsWebAssemblyThemingModule), + typeof(AbpAutoMapperModule), + typeof(AbpAccountHttpApiClientModule) + )] + public class AbpAccountBlazorModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAutoMapperObjectMapper(); + + Configure(options => + { + options.AddProfile(validate: true); + }); + + Configure(options => + { + options.MenuContributors.Add(new AbpAccountBlazorUserMenuContributor()); + }); + + Configure(options => + { + options.AdditionalAssemblies.Add(typeof(AbpAccountBlazorModule).Assembly); + }); + } + } +} diff --git a/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorUserMenuContributor.cs b/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorUserMenuContributor.cs new file mode 100644 index 0000000000..3ceab0f735 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorUserMenuContributor.cs @@ -0,0 +1,23 @@ +using System.Threading.Tasks; +using Volo.Abp.Account.Localization; +using Volo.Abp.UI.Navigation; + +namespace Volo.Abp.Account.Blazor +{ + public class AbpAccountBlazorUserMenuContributor : IMenuContributor + { + public Task ConfigureMenuAsync(MenuConfigurationContext context) + { + if (context.Menu.Name != StandardMenus.User) + { + return Task.CompletedTask; + } + + var accountResource = context.GetLocalizer(); + + context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", accountResource["ManageYourProfile"], url: "account/manage-profile", icon: "fa fa-cog")); + + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Blazor/FodyWeavers.xml b/modules/account/src/Volo.Abp.Account.Blazor/FodyWeavers.xml new file mode 100644 index 0000000000..be0de3a908 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Blazor/FodyWeavers.xsd b/modules/account/src/Volo.Abp.Account.Blazor/FodyWeavers.xsd new file mode 100644 index 0000000000..3f3946e282 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/Manage.razor b/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/Manage.razor new file mode 100644 index 0000000000..d8c9d063b8 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/Manage.razor @@ -0,0 +1,64 @@ +@page "/account/manage-profile" +@inherits AccountManageBase + + + + + @L["ProfileTab:Password"] + @L["ProfileTab:PersonalInfo"] + + + @if (ChangePasswordModel != null) + { + + + @L["DisplayName:CurrentPassword"] + + + + @L["DisplayName:NewPassword"] + + + + @L["DisplayName:NewPasswordConfirm"] + + + + + + + } + @if (PersonalInfoModel != null) + { + + + @L["DisplayName:UserName"] + + + + + @L["DisplayName:Name"] + + + + @L["DisplayName:Surname"] + + + + + @L["DisplayName:Email"] + + + + @L["DisplayName:PhoneNumber"] + + + + + + + } + + + + \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/Manage.razor.cs b/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/Manage.razor.cs new file mode 100644 index 0000000000..77cf43327c --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/Manage.razor.cs @@ -0,0 +1,117 @@ +using System.Threading.Tasks; +using Localization.Resources.AbpUi; +using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; +using Volo.Abp.Account.Localization; +using Volo.Abp.AspNetCore.Components.WebAssembly; +using Volo.Abp.Identity; +using Volo.Abp.ObjectMapping; + +namespace Volo.Abp.Account.Blazor.Pages.Account +{ + public class AccountManageBase : OwningComponentBase + { + [Inject] protected IAccountAppService AccountAppService { get; set; } + [Inject] protected IProfileAppService ProfileAppService { get; set; } + + [Inject] protected IObjectMapper ObjectMapper { get; set; } + + [Inject] protected IUiMessageService UiMessageService { get; set; } + + [Inject] protected IStringLocalizer UiLocalizer { get; set; } + + [Inject] protected IStringLocalizer L { get; set; } + + protected string SelectedTab = "Password"; + + protected ChangePasswordModel ChangePasswordModel; + + protected PersonalInfoModel PersonalInfoModel; + + protected override async Task OnInitializedAsync() + { + await GetUserInformations(); + } + + protected async Task GetUserInformations() + { + var user = await ProfileAppService.GetAsync(); + + ChangePasswordModel = new ChangePasswordModel + { + HideOldPasswordInput = !user.HasPassword + }; + + PersonalInfoModel = ObjectMapper.Map(user); + } + + protected async Task ChangePasswordAsync() + { + if (string.IsNullOrWhiteSpace(ChangePasswordModel.CurrentPassword)) + { + return; + } + + if (ChangePasswordModel.NewPassword != ChangePasswordModel.NewPasswordConfirm) + { + await UiMessageService.WarnAsync(L["NewPasswordConfirmFailed"]); + return; + } + + if (!await UiMessageService.ConfirmAsync(UiLocalizer["AreYouSure"])) + { + return; + } + + await ProfileAppService.ChangePasswordAsync(new ChangePasswordInput + { + CurrentPassword = ChangePasswordModel.CurrentPassword, + NewPassword = ChangePasswordModel.NewPassword + }); + + await UiMessageService.SuccessAsync(L["PasswordChanged"]); + } + + protected async Task UpdatePersonalInfoAsync() + { + if (!await UiMessageService.ConfirmAsync(UiLocalizer["AreYouSure"])) + { + return; + } + + await ProfileAppService.UpdateAsync( + ObjectMapper.Map(PersonalInfoModel) + ); + + await UiMessageService.SuccessAsync(L["PersonalSettingsSaved"]); + } + } + + public class ChangePasswordModel + { + public string CurrentPassword { get; set; } + + public string NewPassword { get; set; } + + public string NewPasswordConfirm { get; set; } + + public bool HideOldPasswordInput { get; set; } + } + + public class PersonalInfoModel + { + public string UserName { get; set; } + + public string Email { get; set; } + + public string Name { get; set; } + + public string Surname { get; set; } + + public string PhoneNumber { get; set; } + + public bool PhoneNumberConfirmed { get; set; } + + public bool EmailConfirmed { get; set; } + } +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Blazor/Volo.Abp.Account.Blazor.csproj b/modules/account/src/Volo.Abp.Account.Blazor/Volo.Abp.Account.Blazor.csproj new file mode 100644 index 0000000000..5707bc86a4 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor/Volo.Abp.Account.Blazor.csproj @@ -0,0 +1,27 @@ + + + + + + + netstandard2.1 + 3.0 + Volo.Abp.Account.Blazor + + + + + + + + + + + + + + true + + + + diff --git a/modules/account/src/Volo.Abp.Account.Blazor/_Imports.razor b/modules/account/src/Volo.Abp.Account.Blazor/_Imports.razor new file mode 100644 index 0000000000..4685ac9893 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor/_Imports.razor @@ -0,0 +1,5 @@ +@using Microsoft.AspNetCore.Components.Web +@using Volo.Abp.AspNetCore.Components.WebAssembly +@using Volo.Abp.BlazoriseUI +@using Blazorise +@using Blazorise.DataGrid \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor index c0298aabcc..fca4cf1913 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/RoleManagement.razor @@ -72,8 +72,8 @@ - @L["DisplayName:IsDefault"] - @L["DisplayName:IsPublic"] + @L["DisplayName:IsDefault"] + @L["DisplayName:IsPublic"] @@ -98,8 +98,8 @@ - @L["DisplayName:IsDefault"] - @L["DisplayName:IsPublic"] + @L["DisplayName:IsDefault"] + @L["DisplayName:IsPublic"] diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor index dacc975bb0..ca813229c3 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/Pages/Identity/UserManagement.razor @@ -102,10 +102,10 @@ - @L["DisplayName:LockoutEnabled"] + @L["DisplayName:LockoutEnabled"] - @L["DisplayName:TwoFactorEnabled"] + @L["DisplayName:TwoFactorEnabled"] diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index 142f3de79f..b3f6321b92 100644 --- a/npm/ng-packs/package.json +++ b/npm/ng-packs/package.json @@ -39,6 +39,7 @@ "@angular-builders/jest": "^10.0.0", "@angular-devkit/build-angular": "~0.1000.6", "@angular-devkit/build-ng-packagr": "~0.1000.6", + "@angular-devkit/schematics-cli": "^0.1001.1", "@angular/animations": "~10.0.10", "@angular/cli": "~10.0.6", "@angular/common": "~10.0.10", diff --git a/npm/ng-packs/packages/core/src/lib/models/rest.ts b/npm/ng-packs/packages/core/src/lib/models/rest.ts index 2f0e175002..03d70161bc 100644 --- a/npm/ng-packs/packages/core/src/lib/models/rest.ts +++ b/npm/ng-packs/packages/core/src/lib/models/rest.ts @@ -34,7 +34,7 @@ export namespace Rest { [param: string]: any; }; reportProgress?: boolean; - responseType?: ResponseType; + responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; url: string; withCredentials?: boolean; } diff --git a/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html b/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html index cceef3409c..f857487e1e 100644 --- a/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html +++ b/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html @@ -9,19 +9,22 @@