Allow to add new tabs to the account profile manage page

pull/5257/head
Yunus Emre Kalkan 5 years ago
parent 296ed5464a
commit a3685d4d5b

@ -53,6 +53,8 @@
"ResetPassword_Information": "Please enter your new password.",
"YourPasswordIsSuccessfullyReset": "Your password is successfully reset.",
"GoToTheApplication": "Go to the application",
"BackToLogin": "Back to login"
"BackToLogin": "Back to login",
"ProfileTab:Password": "Change password",
"ProfileTab:PersonalInfo": "Personal info"
}
}

@ -52,6 +52,8 @@
"ResetPassword_Information": "Lütfen yeni şifrenizi belirleyin.",
"YourPasswordIsSuccessfullyReset": "Şifreniz başarıyla sıfırlandı.",
"GoToTheApplication": "Uygulamaya git",
"BackToLogin": "Girişe dön"
"BackToLogin": "Girişe dön",
"ProfileTab:Password": "Şifre değiştir",
"ProfileTab:PersonalInfo": "Kişisel bilgiler"
}
}

@ -1,6 +1,7 @@
using Volo.Abp.Account.Web.Pages.Account;
using Volo.Abp.Identity;
using AutoMapper;
using Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.PersonalInfo;
namespace Volo.Abp.Account.Web
{
@ -8,7 +9,7 @@ namespace Volo.Abp.Account.Web
{
public AbpAccountWebAutoMapperProfile()
{
CreateMap<ProfileDto, PersonalSettingsInfoModel>();
CreateMap<ProfileDto, AccountProfilePersonalInfoManagementGroupViewComponent.PersonalInfoModel>();
}
}
}

@ -1,7 +1,10 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Account.Localization;
using Volo.Abp.Account.Web.Pages.Account;
using Volo.Abp.Account.Web.ProfileManagement;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars;
using Volo.Abp.AutoMapper;
@ -50,16 +53,38 @@ namespace Volo.Abp.Account.Web
options.Contributors.Add(new AccountModuleToolbarContributor());
});
ConfigureProfileManagementPage();
context.Services.AddAutoMapperObjectMapper<AbpAccountWebModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<AbpAccountWebAutoMapperProfile>(validate: true);
});
}
private void ConfigureProfileManagementPage()
{
Configure<RazorPagesOptions>(options =>
{
options.Conventions.AuthorizePage("/Account/Manage");
});
context.Services.AddAutoMapperObjectMapper<AbpAccountWebModule>();
Configure<AbpAutoMapperOptions>(options =>
Configure<ProfileManagementPageOptions>(options =>
{
options.AddProfile<AbpAccountWebAutoMapperProfile>(validate: true);
options.Contributors.Add(new AccountProfileManagementPageContributor());
});
Configure<AbpBundlingOptions>(options =>
{
options.ScriptBundles
.Configure(typeof(ManageModel).FullName,
configuration =>
{
configuration.AddFiles("/Pages/Account/Components/ProfileManagementGroup/Password/Default.js");
configuration.AddFiles("/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.js");
});
});
}
}
}

@ -0,0 +1,59 @@
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Auditing;
using Volo.Abp.Identity;
using Volo.Abp.Validation;
namespace Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.Password
{
public class AccountProfilePasswordManagementGroupViewComponent : AbpViewComponent
{
private readonly IProfileAppService _profileAppService;
public AccountProfilePasswordManagementGroupViewComponent(
IProfileAppService profileAppService)
{
_profileAppService = profileAppService;
}
public async Task<IViewComponentResult> InvokeAsync()
{
var user = await _profileAppService.GetAsync();
var model = new ChangePasswordInfoModel
{
HideOldPasswordInput = !user.HasPassword
};
return View("~/Pages/Account/Components/ProfileManagementGroup/Password/Default.cshtml", model);
}
public class ChangePasswordInfoModel
{
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))]
[Display(Name = "DisplayName:CurrentPassword")]
[DataType(DataType.Password)]
[DisableAuditing]
public string CurrentPassword { get; set; }
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))]
[Display(Name = "DisplayName:NewPassword")]
[DataType(DataType.Password)]
[DisableAuditing]
public string NewPassword { get; set; }
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))]
[Display(Name = "DisplayName:NewPasswordConfirm")]
[DataType(DataType.Password)]
[DisableAuditing]
public string NewPasswordConfirm { get; set; }
public bool HideOldPasswordInput { get; set; }
}
}
}

@ -0,0 +1,17 @@
@using Volo.Abp.Account.Localization
@using Volo.Abp.Users
@using Microsoft.AspNetCore.Mvc.Localization
@inject IHtmlLocalizer<AccountResource> L
@inject ICurrentUser CurrentUser
@model Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.Password.AccountProfilePasswordManagementGroupViewComponent.ChangePasswordInfoModel
<h4>@L["ChangePassword"]</h4><hr/>
<form id="ChangePasswordForm">
@if (!Model.HideOldPasswordInput)
{
<abp-input asp-for="CurrentPassword"/>
}
<abp-input asp-for="NewPassword"/>
<abp-input asp-for="NewPasswordConfirm"/>
<abp-button type="submit" button-type="Primary" text="@L["Submit"].Value"/>
</form>

@ -0,0 +1,31 @@
(function ($) {
$(function () {
var l = abp.localization.getResource("AbpAccount");
$('#ChangePasswordForm').submit(function (e) {
e.preventDefault();
if (!$('#ChangePasswordForm').valid()) {
return false;
}
var input = $('#ChangePasswordForm').serializeFormToObject();
if (
input.newPassword != input.newPasswordConfirm ||
input.newPassword == ''
) {
abp.message.error(l('NewPasswordConfirmFailed'));
return;
}
if (input.currentPassword && input.currentPassword == ''){
return;
}
volo.abp.identity.profile.changePassword(input).then(function (result) {
abp.message.success(l('PasswordChanged'));
});
});
});
})(jQuery);

@ -0,0 +1,56 @@
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Identity;
using Volo.Abp.Validation;
namespace Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.PersonalInfo
{
public class AccountProfilePersonalInfoManagementGroupViewComponent : AbpViewComponent
{
private readonly IProfileAppService _profileAppService;
public AccountProfilePersonalInfoManagementGroupViewComponent(
IProfileAppService profileAppService)
{
_profileAppService = profileAppService;
ObjectMapperContext = typeof(AbpAccountWebModule);
}
public async Task<IViewComponentResult> InvokeAsync()
{
var user = await _profileAppService.GetAsync();
var model = ObjectMapper.Map<ProfileDto, PersonalInfoModel>(user);
return View("~/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.cshtml", model);
}
public class PersonalInfoModel
{
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxUserNameLength))]
[Display(Name = "DisplayName:UserName")]
public string UserName { get; set; }
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxEmailLength))]
[Display(Name = "DisplayName:Email")]
public string Email { get; set; }
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxNameLength))]
[Display(Name = "DisplayName:Name")]
public string Name { get; set; }
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxSurnameLength))]
[Display(Name = "DisplayName:Surname")]
public string Surname { get; set; }
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPhoneNumberLength))]
[Display(Name = "DisplayName:PhoneNumber")]
public string PhoneNumber { get; set; }
}
}
}

@ -0,0 +1,39 @@
@using Volo.Abp.Account.Localization
@using Volo.Abp.Users
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Theming
@using Volo.Abp.Identity.Settings
@using Volo.Abp.Settings
@inject IHtmlLocalizer<AccountResource> L
@inject ICurrentUser CurrentUser
@inject ISettingProvider SettingManager
@inject IThemeManager ThemeManager
@model Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.PersonalInfo.AccountProfilePersonalInfoManagementGroupViewComponent.PersonalInfoModel
@{
var isUserNameUpdateEnabled = string.Equals(await SettingManager.GetOrNullAsync(IdentitySettingNames.User.IsUserNameUpdateEnabled), "true",
StringComparison.OrdinalIgnoreCase);
var isEmailUpdateEnabled = string.Equals(await SettingManager.GetOrNullAsync(IdentitySettingNames.User.IsEmailUpdateEnabled), "true",
StringComparison.OrdinalIgnoreCase);
}
<h4>@L["PersonalSettings"]</h4><hr/>
<form method="post" id="PersonalSettingsForm">
<abp-input asp-for="UserName" readonly="!isUserNameUpdateEnabled"/>
<abp-row>
<abp-column size-md="_6">
<abp-input asp-for="Name"/>
</abp-column>
<abp-column size-md="_6">
<abp-input asp-for="Surname"/>
</abp-column>
</abp-row>
<abp-input asp-for="Email" readonly="!isEmailUpdateEnabled"/>
<abp-input asp-for="PhoneNumber"/>
<abp-button type="submit" button-type="Primary" text="@L["Submit"].Value"/>
</form>

@ -0,0 +1,19 @@
(function ($) {
$(function () {
var l = abp.localization.getResource("AbpAccount");
$('#PersonalSettingsForm').submit(function (e) {
e.preventDefault();
if (!$('#PersonalSettingsForm').valid()) {
return false;
}
var input = $('#PersonalSettingsForm').serializeFormToObject();
volo.abp.identity.profile.update(input).then(function (result) {
abp.notify.success(l('PersonalSettingsSaved'));
});
});
});
})(jQuery);

@ -2,66 +2,33 @@
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@using Volo.Abp.Account.Web.Pages.Account
@using Volo.Abp.Identity.Settings
@using Volo.Abp.Settings
@using Volo.Abp.AspNetCore.Mvc.UI.Theming
@inject ISettingProvider SettingManager
@inject IThemeManager ThemeManager
@inject IHtmlLocalizer<AccountResource> L
@model ManageModel
@{
Layout = ThemeManager.CurrentTheme.GetApplicationLayout();
var isUserNameUpdateEnabled = string.Equals(await SettingManager.GetOrNullAsync(IdentitySettingNames.User.IsUserNameUpdateEnabled), "true",
StringComparison.OrdinalIgnoreCase);
var isEmailUpdateEnabled = string.Equals(await SettingManager.GetOrNullAsync(IdentitySettingNames.User.IsEmailUpdateEnabled), "true",
StringComparison.OrdinalIgnoreCase);
}
@section scripts {
<abp-script-bundle name="@typeof(ManageModel).FullName">
<abp-script src="/Pages/Account/Manage.js" />
</abp-script-bundle>
<abp-script-bundle name="@typeof(ManageModel).FullName"/>
}
<abp-card>
<abp-card-body>
<abp-tabs tab-style="PillVertical">
@if (!Model.DisablePasswordChange)
{
<abp-tab title="@L["ChangePassword"].Value">
<h4>@L["ChangePassword"].Value</h4><hr/>
<form id="ChangePasswordForm">
@if (!Model.HideOldPasswordInput)
{
<abp-input asp-for="ChangePasswordInfoModel.CurrentPassword"/>
}
<abp-input asp-for="ChangePasswordInfoModel.NewPassword"/>
<abp-input asp-for="ChangePasswordInfoModel.NewPasswordConfirm"/>
<abp-button type="submit" button-type="Primary" text="@L["Submit"].Value"/>
</form>
</abp-tab>
}
<abp-tab title="@L["PersonalSettings"].Value">
<h4>@L["PersonalSettings"].Value</h4><hr/>
<form method="post" id="PersonalSettingsForm">
<abp-input asp-for="PersonalSettingsInfoModel.UserName" readonly="!isUserNameUpdateEnabled"/>
<abp-row>
<abp-column size-md="_6">
<abp-input asp-for="PersonalSettingsInfoModel.Name"/>
</abp-column>
<abp-column size-md="_6">
<abp-input asp-for="PersonalSettingsInfoModel.Surname"/>
</abp-column>
</abp-row>
<abp-input asp-for="PersonalSettingsInfoModel.Email" readonly="!isEmailUpdateEnabled"/>
<abp-input asp-for="PersonalSettingsInfoModel.PhoneNumber"/>
<abp-button type="submit" button-type="Primary" text="@L["Submit"].Value"/>
</form>
</abp-tab>
</abp-tabs>
</abp-card-body>
</abp-card>
<div id="ProfileManagementWrapper">
<abp-card>
<abp-card-body>
<abp-tabs tab-style="PillVertical" vertical-header-size="_3">
@foreach (var group in Model.ProfileManagementPageCreationContext.Groups)
{
<abp-tab title="@group.DisplayName">
<h2>@group.DisplayName</h2>
<hr class="my-4" />
@await Component.InvokeAsync(group.ComponentType, new
{
parameter = group.Parameter
})
</abp-tab>
}
</abp-tabs>
</abp-card-body>
</abp-card>
</div>

@ -2,35 +2,31 @@
using System.Threading.Tasks;
using Volo.Abp.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.Account.Web.ProfileManagement;
using Volo.Abp.Validation;
namespace Volo.Abp.Account.Web.Pages.Account
{
public class ManageModel : AccountPageModel
{
public ChangePasswordInfoModel ChangePasswordInfoModel { get; set; }
public ProfileManagementPageCreationContext ProfileManagementPageCreationContext { get; private set; }
public PersonalSettingsInfoModel PersonalSettingsInfoModel { get; set; }
protected ProfileManagementPageOptions Options { get; }
public bool DisablePasswordChange { get; set; }
public bool HideOldPasswordInput { get; set; }
protected IProfileAppService ProfileAppService { get; }
public ManageModel(IProfileAppService profileAppService)
public ManageModel(IOptions<ProfileManagementPageOptions> options)
{
ProfileAppService = profileAppService;
Options = options.Value;
}
public virtual async Task<IActionResult> OnGetAsync()
{
var user = await ProfileAppService.GetAsync();
PersonalSettingsInfoModel = ObjectMapper.Map<ProfileDto, PersonalSettingsInfoModel>(user);
ProfileManagementPageCreationContext = new ProfileManagementPageCreationContext(ServiceProvider);
DisablePasswordChange = user.IsExternal;
HideOldPasswordInput = !user.HasPassword;
foreach (var contributor in Options.Contributors)
{
await contributor.ConfigureAsync(ProfileManagementPageCreationContext);
}
return Page();
}
@ -40,50 +36,4 @@ namespace Volo.Abp.Account.Web.Pages.Account
return Task.FromResult<IActionResult>(Page());
}
}
public class ChangePasswordInfoModel
{
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))]
[Display(Name = "DisplayName:CurrentPassword")]
[DataType(DataType.Password)]
public string CurrentPassword { get; set; }
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))]
[Display(Name = "DisplayName:NewPassword")]
[DataType(DataType.Password)]
public string NewPassword { get; set; }
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))]
[Display(Name = "DisplayName:NewPasswordConfirm")]
[DataType(DataType.Password)]
public string NewPasswordConfirm { get; set; }
}
public class PersonalSettingsInfoModel
{
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxUserNameLength))]
[Display(Name = "DisplayName:UserName")]
public string UserName { get; set; }
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxEmailLength))]
[Display(Name = "DisplayName:Email")]
public string Email { get; set; }
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxNameLength))]
[Display(Name = "DisplayName:Name")]
public string Name { get; set; }
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxSurnameLength))]
[Display(Name = "DisplayName:Surname")]
public string Surname { get; set; }
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPhoneNumberLength))]
[Display(Name = "DisplayName:PhoneNumber")]
public string PhoneNumber { get; set; }
}
}

@ -1,47 +0,0 @@
(function ($) {
var l = abp.localization.getResource('AbpAccount');
var _profileService = volo.abp.identity.profile;
$('#ChangePasswordForm').submit(function (e) {
e.preventDefault();
if (!$('#ChangePasswordForm').valid()) {
return false;
}
var input = $('#ChangePasswordForm').serializeFormToObject()
.changePasswordInfoModel;
if (
input.newPassword != input.newPasswordConfirm ||
input.newPassword == ''
) {
abp.message.error(l('NewPasswordConfirmFailed'));
return;
}
if (input.currentPassword && input.currentPassword == ''){
return;
}
_profileService.changePassword(input).then(function (result) {
abp.message.success(l('PasswordChanged'));
});
});
$('#PersonalSettingsForm').submit(function (e) {
e.preventDefault();
if (!$('#PersonalSettingsForm').valid()) {
return false;
}
var input = $('#PersonalSettingsForm').serializeFormToObject()
.personalSettingsInfoModel;
_profileService.update(input).then(function (result) {
abp.notify.success(l('PersonalSettingsSaved'));
});
});
})(jQuery);

@ -18,7 +18,6 @@ namespace Volo.Abp.Account.Web.Pages.Account
{
public class RegisterModel : AccountPageModel
{
protected IAccountAppService AccountAppService { get; }
[BindProperty(SupportsGet = true)]
public string ReturnUrl { get; set; }

@ -0,0 +1,48 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Volo.Abp.Account.Localization;
using Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.Password;
using Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.PersonalInfo;
using Volo.Abp.Identity;
using Volo.Abp.Users;
namespace Volo.Abp.Account.Web.ProfileManagement
{
public class AccountProfileManagementPageContributor : IProfileManagementPageContributor
{
public async Task ConfigureAsync(ProfileManagementPageCreationContext context)
{
var l = context.ServiceProvider.GetRequiredService<IStringLocalizer<AccountResource>>();
if (await IsPasswordChangeEnabled(context))
{
context.Groups.Add(
new ProfileManagementPageGroup(
"Volo.Abp.Account.Password",
l["ProfileTab:Password"],
typeof(AccountProfilePasswordManagementGroupViewComponent)
)
);
}
context.Groups.Add(
new ProfileManagementPageGroup(
"Volo.Abp.Account.PersonalInfo",
l["ProfileTab:PersonalInfo"],
typeof(AccountProfilePersonalInfoManagementGroupViewComponent)
)
);
}
protected virtual async Task<bool> IsPasswordChangeEnabled(ProfileManagementPageCreationContext context)
{
var userManager = context.ServiceProvider.GetRequiredService<IdentityUserManager>();
var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>();
var user = await userManager.GetByIdAsync(currentUser.GetId());
return !user.IsExternal;
}
}
}

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Volo.Abp.Account.Web.ProfileManagement
{
public interface IProfileManagementPageContributor
{
Task ConfigureAsync(ProfileManagementPageCreationContext context);
}
}

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.Account.Web.ProfileManagement
{
public class ProfileManagementPageCreationContext
{
public IServiceProvider ServiceProvider { get; }
public List<ProfileManagementPageGroup> Groups { get; }
public ProfileManagementPageCreationContext(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
Groups = new List<ProfileManagementPageGroup>();
}
}
}

@ -0,0 +1,39 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.Account.Web.ProfileManagement
{
public class ProfileManagementPageGroup
{
public string Id
{
get => _id;
set => _id = Check.NotNullOrWhiteSpace(value, nameof(Id));
}
private string _id;
public string DisplayName
{
get => _displayName;
set => _displayName = Check.NotNullOrWhiteSpace(value, nameof(DisplayName));
}
private string _displayName;
public Type ComponentType
{
get => _componentType;
set => _componentType = Check.NotNull(value, nameof(ComponentType));
}
private Type _componentType;
public object Parameter { get; set; }
public ProfileManagementPageGroup([NotNull] string id, [NotNull] string displayName, [NotNull] Type componentType, object parameter = null)
{
Id = id;
DisplayName = displayName;
ComponentType = componentType;
Parameter = parameter;
}
}
}

@ -0,0 +1,14 @@
using System.Collections.Generic;
namespace Volo.Abp.Account.Web.ProfileManagement
{
public class ProfileManagementPageOptions
{
public List<IProfileManagementPageContributor> Contributors { get; }
public ProfileManagementPageOptions()
{
Contributors = new List<IProfileManagementPageContributor>();
}
}
}
Loading…
Cancel
Save