diff --git a/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/AbpAccountBlazorMappers.cs b/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/AbpAccountBlazorMappers.cs new file mode 100644 index 0000000000..eda8b42eb9 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/AbpAccountBlazorMappers.cs @@ -0,0 +1,27 @@ +using Riok.Mapperly.Abstractions; +using Volo.Abp.Account.Blazor.MudBlazor.Pages.Account; +using Volo.Abp.Mapperly; +using Volo.Abp.Identity; + +namespace Volo.Abp.Account.Blazor.MudBlazor; + +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] +[MapExtraProperties] +public partial class ProfileDtoToPersonalInfoModelMapper : MapperBase +{ + [MapperIgnoreTarget(nameof(PersonalInfoModel.PhoneNumberConfirmed))] + [MapperIgnoreTarget(nameof(PersonalInfoModel.EmailConfirmed))] + public override partial PersonalInfoModel Map(ProfileDto source); + + [MapperIgnoreTarget(nameof(PersonalInfoModel.PhoneNumberConfirmed))] + [MapperIgnoreTarget(nameof(PersonalInfoModel.EmailConfirmed))] + public override partial void Map(ProfileDto source, PersonalInfoModel destination); +} + +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] +[MapExtraProperties] +public partial class PersonalInfoModelToUpdateProfileDtoMapper : MapperBase +{ + public override partial UpdateProfileDto Map(PersonalInfoModel source); + public override partial void Map(PersonalInfoModel source, UpdateProfileDto destination); +} diff --git a/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/AbpAccountBlazorUserMenuContributor.cs b/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/AbpAccountBlazorUserMenuContributor.cs new file mode 100644 index 0000000000..bbb230938d --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/AbpAccountBlazorUserMenuContributor.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; +using Volo.Abp.Account.Localization; +using Volo.Abp.UI.Navigation; + +namespace Volo.Abp.Account.Blazor.MudBlazor; + +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["MyAccount"], url: "account/manage-profile", icon: "fa fa-cog")); + + return Task.CompletedTask; + } +} diff --git a/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/AbpAccountComponentBase.cs b/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/AbpAccountComponentBase.cs new file mode 100644 index 0000000000..b2c1f74c67 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/AbpAccountComponentBase.cs @@ -0,0 +1,13 @@ +using Volo.Abp.Account.Localization; +using Volo.Abp.AspNetCore.Components; + +namespace Volo.Abp.Account.Blazor.MudBlazor; + +public abstract class AbpAccountComponentBase : AbpComponentBase +{ + protected AbpAccountComponentBase() + { + LocalizationResource = typeof(AccountResource); + ObjectMapperContext = typeof(AbpAccountBlazorMudBlazorModule); + } +} diff --git a/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/Pages/Account/AccountManage.razor b/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/Pages/Account/AccountManage.razor new file mode 100644 index 0000000000..4a1a0f8992 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/Pages/Account/AccountManage.razor @@ -0,0 +1,113 @@ +@page "/account/manage-profile" +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.Extensions.Localization +@using Volo.Abp.Account.Localization +@using Volo.Abp.AspNetCore.Components.Web +@using Volo.Abp.MudBlazorUI.Components.ObjectExtending +@using Volo.Abp.ObjectExtending +@using Volo.Abp.Data +@using Volo.Abp.Identity + +@inject IStringLocalizer Localizer +@inherits AbpAccountComponentBase + + + + + + @if (ChangePasswordModel != null) + { + + + + + + @L["Save"] + + + } + + + @if (PersonalInfoModel != null) + { + + + + + + + + + + + + + + @* Extension Properties *@ + @foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties()) + { + var isAllowed = propertyInfo.Configuration.GetOrDefault(IdentityModuleExtensionConsts.ConfigurationNames.AllowUserToEdit); + + if (isAllowed == null || !isAllowed.Equals(true)) + { + continue; + } + + if (!propertyInfo.Name.EndsWith("_Text")) + { + if (propertyInfo.IsEnum()) + { + + } + else if (!propertyInfo.Lookup.Url.IsNullOrEmpty()) + { + + } + else + { + var inputType = propertyInfo.GetInputType(); + __builder.OpenComponent(0, inputType.MakeGenericType(new[] { typeof(PersonalInfoModel), typeof(AccountResource) })); + __builder.AddAttribute(1, "PropertyInfo", propertyInfo); + __builder.AddAttribute(2, "Entity", PersonalInfoModel); + __builder.AddAttribute(3, "LH", _localizerHelper); + __builder.CloseComponent(); + } + } + } + + + @L["Save"] + + + } + + + + + diff --git a/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/Pages/Account/AccountManage.razor.cs b/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/Pages/Account/AccountManage.razor.cs new file mode 100644 index 0000000000..7d4aba25d9 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/Pages/Account/AccountManage.razor.cs @@ -0,0 +1,142 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; +using MudBlazor; +using Volo.Abp.AspNetCore.Components.Messages; +using Volo.Abp.Identity; +using Volo.Abp.MudBlazorUI; +using Volo.Abp.ObjectExtending; + +namespace Volo.Abp.Account.Blazor.MudBlazor.Pages.Account; + +public partial class AccountManage +{ + [Inject] protected IProfileAppService ProfileAppService { get; set; } = default!; + + [Inject] protected IUiMessageService UiMessageService { get; set; } = default!; + + [Inject] protected ISnackbar Snackbar { get; set; } = default!; + + [Inject] protected IStringLocalizer Localizer { get; set; } = default!; + + protected string SelectedTab = "Password"; + + protected ChangePasswordModel? ChangePasswordModel; + + protected PersonalInfoModel? PersonalInfoModel; + + private int _activeTabIndex = 0; + private MudForm? _changePasswordForm; + private MudForm? _personalInfoForm; + private AbpMudBlazorMessageLocalizerHelper? _localizerHelper; + + protected override async Task OnInitializedAsync() + { + _localizerHelper = new AbpMudBlazorMessageLocalizerHelper(Localizer); + 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 (_changePasswordForm == null || !await _changePasswordForm.Validate()) + { + return; + } + + if (ChangePasswordModel == null || string.IsNullOrWhiteSpace(ChangePasswordModel.CurrentPassword)) + { + return; + } + + if (ChangePasswordModel.NewPassword != ChangePasswordModel.NewPasswordConfirm) + { + await UiMessageService.Warn(L["NewPasswordConfirmFailed"]); + return; + } + + if (ChangePasswordModel.CurrentPassword == ChangePasswordModel.NewPassword) + { + await UiMessageService.Warn(L["NewPasswordSameAsOld"]); + return; + } + + await ProfileAppService.ChangePasswordAsync(new ChangePasswordInput + { + CurrentPassword = ChangePasswordModel.CurrentPassword, + NewPassword = ChangePasswordModel.NewPassword + }); + + ChangePasswordModel.Clear(); + + await UiMessageService.Success(L["PasswordChanged"]); + } + + protected virtual async Task UpdatePersonalInfoAsync() + { + if (_personalInfoForm == null || !await _personalInfoForm.Validate()) + { + return; + } + + if (PersonalInfoModel == null) + { + return; + } + + await ProfileAppService.UpdateAsync( + ObjectMapper.Map(PersonalInfoModel) + ); + + await UiMessageService.Success(L["PersonalSettingsSaved"]); + } + +} + +public class ChangePasswordModel +{ + public string CurrentPassword { get; set; } = string.Empty; + + public string NewPassword { get; set; } = string.Empty; + + public string NewPasswordConfirm { get; set; } = string.Empty; + + public bool HideOldPasswordInput { get; set; } + + public void Clear() + { + CurrentPassword = string.Empty; + NewPassword = string.Empty; + NewPasswordConfirm = string.Empty; + } +} + +public class PersonalInfoModel : ExtensibleObject +{ + public string UserName { get; set; } = string.Empty; + + public string Email { get; set; } = string.Empty; + + public string Name { get; set; } = string.Empty; + + public string Surname { get; set; } = string.Empty; + + public string PhoneNumber { get; set; } = string.Empty; + + public bool PhoneNumberConfirmed { get; set; } + + public bool EmailConfirmed { get; set; } + + public string ConcurrencyStamp { get; set; } = string.Empty; +} diff --git a/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/_Imports.razor b/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/_Imports.razor new file mode 100644 index 0000000000..97ced1d380 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor.MudBlazor/_Imports.razor @@ -0,0 +1,6 @@ +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.AspNetCore.Components.Forms +@using Volo.Abp.MudBlazorUI +@using Volo.Abp.MudBlazorUI.Components +@using MudBlazor +@using MudBlazor.Components