mirror of https://github.com/abpframework/abp.git
6 changed files with 323 additions and 0 deletions
@ -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<ProfileDto, PersonalInfoModel> |
||||
|
{ |
||||
|
[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<PersonalInfoModel, UpdateProfileDto> |
||||
|
{ |
||||
|
public override partial UpdateProfileDto Map(PersonalInfoModel source); |
||||
|
public override partial void Map(PersonalInfoModel source, UpdateProfileDto destination); |
||||
|
} |
||||
@ -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<AccountResource>(); |
||||
|
|
||||
|
context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", accountResource["MyAccount"], url: "account/manage-profile", icon: "fa fa-cog")); |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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<AccountResource> Localizer |
||||
|
@inherits AbpAccountComponentBase |
||||
|
|
||||
|
<MudGrid> |
||||
|
<MudItem xs="12"> |
||||
|
<MudTabs @bind-ActivePanelIndex="@_activeTabIndex" PanelClass="pa-4"> |
||||
|
<MudTabPanel Text="@L["ProfileTab:Password"]"> |
||||
|
@if (ChangePasswordModel != null) |
||||
|
{ |
||||
|
<MudForm @ref="@_changePasswordForm" Model="@ChangePasswordModel"> |
||||
|
<MudTextField @bind-Value="@ChangePasswordModel.CurrentPassword" |
||||
|
Label="@L["DisplayName:CurrentPassword"]" |
||||
|
InputType="InputType.Password" |
||||
|
Variant="Variant.Outlined" /> |
||||
|
<MudTextField @bind-Value="@ChangePasswordModel.NewPassword" |
||||
|
Label="@L["DisplayName:NewPassword"]" |
||||
|
InputType="InputType.Password" |
||||
|
Variant="Variant.Outlined" /> |
||||
|
<MudTextField @bind-Value="@ChangePasswordModel.NewPasswordConfirm" |
||||
|
Label="@L["DisplayName:NewPasswordConfirm"]" |
||||
|
InputType="InputType.Password" |
||||
|
Variant="Variant.Outlined" /> |
||||
|
<MudButton ButtonType="ButtonType.Submit" |
||||
|
Variant="Variant.Filled" |
||||
|
Color="Color.Primary" |
||||
|
OnClick="@ChangePasswordAsync"> |
||||
|
@L["Save"] |
||||
|
</MudButton> |
||||
|
</MudForm> |
||||
|
} |
||||
|
</MudTabPanel> |
||||
|
<MudTabPanel Text="@L["ProfileTab:PersonalInfo"]"> |
||||
|
@if (PersonalInfoModel != null) |
||||
|
{ |
||||
|
<MudForm @ref="@_personalInfoForm" Model="@PersonalInfoModel"> |
||||
|
<MudTextField @bind-Value="@PersonalInfoModel.UserName" |
||||
|
Label="@L["DisplayName:UserName"]" |
||||
|
Variant="Variant.Outlined" |
||||
|
Disabled="true" /> |
||||
|
<MudGrid> |
||||
|
<MudItem xs="12" sm="6"> |
||||
|
<MudTextField @bind-Value="@PersonalInfoModel.Name" |
||||
|
Label="@L["DisplayName:Name"]" |
||||
|
Variant="Variant.Outlined" /> |
||||
|
</MudItem> |
||||
|
<MudItem xs="12" sm="6"> |
||||
|
<MudTextField @bind-Value="@PersonalInfoModel.Surname" |
||||
|
Label="@L["DisplayName:Surname"]" |
||||
|
Variant="Variant.Outlined" /> |
||||
|
</MudItem> |
||||
|
</MudGrid> |
||||
|
<MudTextField @bind-Value="@PersonalInfoModel.Email" |
||||
|
Label="@L["DisplayName:Email"]" |
||||
|
Variant="Variant.Outlined" /> |
||||
|
<MudTextField @bind-Value="@PersonalInfoModel.PhoneNumber" |
||||
|
Label="@L["DisplayName:PhoneNumber"]" |
||||
|
Variant="Variant.Outlined" /> |
||||
|
|
||||
|
@* Extension Properties *@ |
||||
|
@foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties<PersonalInfoModel>()) |
||||
|
{ |
||||
|
var isAllowed = propertyInfo.Configuration.GetOrDefault(IdentityModuleExtensionConsts.ConfigurationNames.AllowUserToEdit); |
||||
|
|
||||
|
if (isAllowed == null || !isAllowed.Equals(true)) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
if (!propertyInfo.Name.EndsWith("_Text")) |
||||
|
{ |
||||
|
if (propertyInfo.IsEnum()) |
||||
|
{ |
||||
|
<MudSelectExtensionProperty PropertyInfo="@propertyInfo" Entity="@PersonalInfoModel" TEntity="PersonalInfoModel" TResourceType="AccountResource" LH="@_localizerHelper" /> |
||||
|
} |
||||
|
else if (!propertyInfo.Lookup.Url.IsNullOrEmpty()) |
||||
|
{ |
||||
|
<MudLookupExtensionProperty PropertyInfo="@propertyInfo" Entity="@PersonalInfoModel" TEntity="PersonalInfoModel" TResourceType="AccountResource" LH="@_localizerHelper" /> |
||||
|
} |
||||
|
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(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
<MudButton ButtonType="ButtonType.Submit" |
||||
|
Variant="Variant.Filled" |
||||
|
Color="Color.Primary" |
||||
|
OnClick="@UpdatePersonalInfoAsync"> |
||||
|
@L["Save"] |
||||
|
</MudButton> |
||||
|
</MudForm> |
||||
|
} |
||||
|
</MudTabPanel> |
||||
|
</MudTabs> |
||||
|
</MudItem> |
||||
|
</MudGrid> |
||||
|
|
||||
@ -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<AccountResource> 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<AccountResource>? _localizerHelper; |
||||
|
|
||||
|
protected override async Task OnInitializedAsync() |
||||
|
{ |
||||
|
_localizerHelper = new AbpMudBlazorMessageLocalizerHelper<AccountResource>(Localizer); |
||||
|
await GetUserInformations(); |
||||
|
} |
||||
|
|
||||
|
protected async Task GetUserInformations() |
||||
|
{ |
||||
|
var user = await ProfileAppService.GetAsync(); |
||||
|
|
||||
|
ChangePasswordModel = new ChangePasswordModel |
||||
|
{ |
||||
|
HideOldPasswordInput = !user.HasPassword |
||||
|
}; |
||||
|
|
||||
|
PersonalInfoModel = ObjectMapper.Map<ProfileDto, PersonalInfoModel>(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, UpdateProfileDto>(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; |
||||
|
} |
||||
@ -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 |
||||
Loading…
Reference in new issue