diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/UserMenu/Default.cshtml b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/UserMenu/Default.cshtml index 329737c3d2..9f8c9856f5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/UserMenu/Default.cshtml +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/UserMenu/Default.cshtml @@ -21,7 +21,7 @@ var cssClass = string.IsNullOrEmpty(menuItem.CssClass) ? string.Empty : menuItem.CssClass; var disabled = menuItem.IsDisabled ? "disabled" : string.Empty; - + @menuItem.DisplayName } diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json index 892e60f89e..f5167f51f2 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json @@ -16,6 +16,23 @@ "Register": "Register", "InvalidLoginRequest": "Invalid login request", "ThereAreNoLoginSchemesConfiguredForThisClient": "There are no login schemes configured for this client.", - "LogInUsingYourProviderAccount": "Log in using your {0} account" + "LogInUsingYourProviderAccount": "Log in using your {0} account", + "DisplayName:CurrentPassword": "Current password", + "DisplayName:NewPassword": "New password", + "DisplayName:NewPasswordConfirm": "Confirm new password", + "PasswordChangedMessage": "Your password has been changed successfully.", + "DisplayName:UserName": "User name", + "DisplayName:Email": "Email", + "DisplayName:Name": "Name", + "DisplayName:Surname": "Surname", + "DisplayName:Password": "Password", + "DisplayName:EmailAddress": "Email address", + "DisplayName:PhoneNumber": "Phone number", + "PersonalSettings": "Personal settings", + "PersonalSettingsSaved": "Personal settings saved", + "PasswordChanged": "Password changed", + "NewPasswordConfirmFailed": "Please confirm the new password.", + "Manage": "Manage", + "ManageYourProfile": "Manage your profile" } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.csproj b/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.csproj index d65af4ac04..2af9e29df4 100644 --- a/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.csproj +++ b/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.csproj @@ -12,6 +12,7 @@ + diff --git a/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/AbpAccountHttpApiModule.cs b/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/AbpAccountHttpApiModule.cs index 3a58d11643..0e210dd8de 100644 --- a/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/AbpAccountHttpApiModule.cs +++ b/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/AbpAccountHttpApiModule.cs @@ -1,6 +1,7 @@ using Localization.Resources.AbpUi; using Volo.Abp.Account.Localization; using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Identity; using Volo.Abp.Localization; using Volo.Abp.Modularity; @@ -8,6 +9,7 @@ namespace Volo.Abp.Account { [DependsOn( typeof(AbpAccountApplicationContractsModule), + typeof(AbpIdentityHttpApiModule), typeof(AbpAspNetCoreMvcModule))] public class AbpAccountHttpApiModule : AbpModule { diff --git a/modules/account/src/Volo.Abp.Account.Web/AbpAccountUserMenuContributor.cs b/modules/account/src/Volo.Abp.Account.Web/AbpAccountUserMenuContributor.cs index 2741aabe82..9bdd8095ed 100644 --- a/modules/account/src/Volo.Abp.Account.Web/AbpAccountUserMenuContributor.cs +++ b/modules/account/src/Volo.Abp.Account.Web/AbpAccountUserMenuContributor.cs @@ -2,17 +2,13 @@ using Localization.Resources.AbpUi; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; +using Volo.Abp.Account.Localization; using Volo.Abp.UI.Navigation; namespace Volo.Abp.Account.Web { public class AbpAccountUserMenuContributor : IMenuContributor { - public AbpAccountUserMenuContributor() - { - - } - public Task ConfigureMenuAsync(MenuConfigurationContext context) { if (context.Menu.Name != StandardMenus.User) @@ -20,13 +16,11 @@ namespace Volo.Abp.Account.Web return Task.CompletedTask; } - var l = context.ServiceProvider.GetRequiredService>(); - - context.Menu.AddItem(new ApplicationMenuItem("Account.ChangePassword", l["ChangePassword"], icon: "fa fa-key", url: "#", elementId: "abp-account-change-password")); - - context.Menu.AddItem(new ApplicationMenuItem("Account.PersonalSettings", l["PersonalInfo"], icon: "fa fa-info", url: "#", elementId: "abp-account-personal-settings")); + var uiResource = context.ServiceProvider.GetRequiredService>(); + var accountResource = context.ServiceProvider.GetRequiredService>(); - context.Menu.AddItem(new ApplicationMenuItem("Account.Logout", l["Logout"], url: "/Account/Logout", icon: "fa fa-power-off", order: int.MaxValue - 1000)); + context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", accountResource["ManageYourProfile"], url: "/Account/Manage", icon: "fa fa-cog", order: 1000, null)); + context.Menu.AddItem(new ApplicationMenuItem("Account.Logout", uiResource["Logout"], url: "/Account/Logout", icon: "fa fa-power-off", order: int.MaxValue - 1000)); return Task.CompletedTask; } diff --git a/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebAutomapperProfile.cs b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebAutomapperProfile.cs new file mode 100644 index 0000000000..ab7ea41269 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebAutomapperProfile.cs @@ -0,0 +1,14 @@ +using Volo.Abp.Account.Web.Pages.Account; +using Volo.Abp.Identity; +using AutoMapper; + +namespace Volo.Abp.Account.Web +{ + public class AbpAccountWebAutoMapperProfile : Profile + { + public AbpAccountWebAutoMapperProfile() + { + CreateMap(); + } + } +} diff --git a/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs index f7481b3485..5cada69450 100644 --- a/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs +++ b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs @@ -1,8 +1,10 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Account.Localization; using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars; +using Volo.Abp.AutoMapper; using Volo.Abp.Identity.AspNetCore; using Volo.Abp.Modularity; using Volo.Abp.UI.Navigation; @@ -13,6 +15,7 @@ namespace Volo.Abp.Account.Web [DependsOn( typeof(AbpAccountHttpApiModule), typeof(AbpIdentityAspNetCoreModule), + typeof(AbpAutoMapperModule), typeof(AbpAspNetCoreMvcUiThemeSharedModule) )] public class AbpAccountWebModule : AbpModule @@ -41,6 +44,16 @@ namespace Volo.Abp.Account.Web { options.Contributors.Add(new AccountModuleToolbarContributor()); }); + + Configure(options => + { + options.Conventions.AuthorizePage("/Account/Manage"); + }); + + Configure(options => + { + options.AddProfile(validate: true); + }); } } } diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml new file mode 100644 index 0000000000..36c94271d1 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml @@ -0,0 +1,50 @@ +@page +@model Volo.Abp.Account.Web.Pages.Account.ManageModel +@using Volo.Abp.Identity.Settings +@using Volo.Abp.Settings +@using Volo.Abp.AspNetCore.Mvc.UI.Theming +@inject ISettingProvider SettingManager +@inject IThemeManager ThemeManager +@inherits Volo.Abp.Account.Web.Pages.Account.AccountPage +@{ + 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 { + +} + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ +
\ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/PersonalSettingsModal.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml.cs similarity index 56% rename from modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/PersonalSettingsModal.cshtml.cs rename to modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml.cs index 8d1152b3fb..9fba470929 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/PersonalSettingsModal.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml.cs @@ -1,18 +1,18 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Identity; -namespace Volo.Abp.Identity.Web.Pages.Identity.Shared +namespace Volo.Abp.Account.Web.Pages.Account { - public class PersonalSettingsModal : AbpPageModel + public class ManageModel : AccountPageModel { - [BindProperty] + public ChangePasswordInfoModel ChangePasswordInfoModel { get; set; } + public PersonalSettingsInfoModel PersonalSettingsInfoModel { get; set; } - + private readonly IProfileAppService _profileAppService; - public PersonalSettingsModal(IProfileAppService profileAppService) + public ManageModel(IProfileAppService profileAppService) { _profileAppService = profileAppService; } @@ -23,19 +23,28 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Shared PersonalSettingsInfoModel = ObjectMapper.Map(user); } + } - public async Task OnPostAsync() - { - ValidateModel(); - - var updateDto = ObjectMapper.Map(PersonalSettingsInfoModel); + public class ChangePasswordInfoModel + { + [Required] + [StringLength(IdentityUserConsts.MaxPasswordLength)] + [Display(Name = "DisplayName:CurrentPassword")] + [DataType(DataType.Password)] + public string CurrentPassword { get; set; } - await _profileAppService.UpdateAsync(updateDto); + [Required] + [StringLength(IdentityUserConsts.MaxPasswordLength)] + [Display(Name = "DisplayName:NewPassword")] + [DataType(DataType.Password)] + public string NewPassword { get; set; } - return NoContent(); - } + [Required] + [StringLength(IdentityUserConsts.MaxPasswordLength)] + [Display(Name = "DisplayName:NewPasswordConfirm")] + [DataType(DataType.Password)] + public string NewPasswordConfirm { get; set; } } - public class PersonalSettingsInfoModel { [Required] diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.js b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.js new file mode 100644 index 0000000000..844151c71b --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.js @@ -0,0 +1,50 @@ +(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.currentPassword == '') { + abp.message.error(l("NewPasswordConfirmFailed")); + return; + } + + if (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); \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj b/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj index 3a15b14105..3101861d54 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj +++ b/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj @@ -29,12 +29,14 @@ + + diff --git a/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebAutoMapperProfile.cs b/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebAutoMapperProfile.cs index 4c991466e9..c8651d8e88 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebAutoMapperProfile.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebAutoMapperProfile.cs @@ -1,6 +1,5 @@ using AutoMapper; using Volo.Abp.Identity.Web.Pages.Identity.Roles; -using Volo.Abp.Identity.Web.Pages.Identity.Shared; using CreateUserModalModel = Volo.Abp.Identity.Web.Pages.Identity.Users.CreateModalModel; using EditUserModalModel = Volo.Abp.Identity.Web.Pages.Identity.Users.EditModalModel; @@ -12,7 +11,6 @@ namespace Volo.Abp.Identity.Web { CreateUserMappings(); CreateRoleMappings(); - CreateProfileMappings(); } private void CreateUserMappings() @@ -33,10 +31,6 @@ namespace Volo.Abp.Identity.Web CreateMap() .ForMember(dest => dest.IsAssigned, opt => opt.Ignore()); - - CreateMap(); - - CreateMap(); } private void CreateRoleMappings() @@ -50,11 +44,5 @@ namespace Volo.Abp.Identity.Web //EditModal CreateMap(); } - - private void CreateProfileMappings() - { - CreateMap(); - CreateMap(); - } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs b/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs index 072c8f3584..077499c48e 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs @@ -59,15 +59,6 @@ namespace Volo.Abp.Identity.Web options.Conventions.AuthorizePage("/Identity/Roles/CreateModal", IdentityPermissions.Roles.Create); options.Conventions.AuthorizePage("/Identity/Roles/EditModal", IdentityPermissions.Roles.Update); }); - - Configure(options => - { - options - .ScriptBundles - .Get(StandardBundles.Scripts.Global) - .AddFiles("/Pages/Identity/Shared/change-password-modal.js") - .AddFiles("/Pages/Identity/Shared/personal-settings-modal.js"); - }); } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/ChangePasswordModal.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/ChangePasswordModal.cshtml deleted file mode 100644 index 54bae13cbe..0000000000 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/ChangePasswordModal.cshtml +++ /dev/null @@ -1,20 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.Localization -@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal -@using Volo.Abp.Identity.Localization -@using Volo.Abp.Identity.Web.Pages.Identity.Shared -@model ChangePasswordModal -@inject IHtmlLocalizer L -@{ - Layout = null; -} - - - - - - - - - - \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/ChangePasswordModal.cshtml.cs b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/ChangePasswordModal.cshtml.cs deleted file mode 100644 index c698b6b6f6..0000000000 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/ChangePasswordModal.cshtml.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Localization; -using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; -using Volo.Abp.Identity.Localization; - -namespace Volo.Abp.Identity.Web.Pages.Identity.Shared -{ - public class ChangePasswordModal : AbpPageModel - { - [BindProperty] - public ChangePasswordInfoModel ChangePasswordInfoModel { get; set; } - - private readonly IProfileAppService _profileAppService; - private readonly IStringLocalizer _localizer; - - public ChangePasswordModal( - IProfileAppService profileAppService, - IStringLocalizer localizer) - { - _profileAppService = profileAppService; - _localizer = localizer; - } - - public async Task OnPostAsync() - { - ValidateModel(); - - if (ChangePasswordInfoModel.NewPassword != ChangePasswordInfoModel.NewPasswordConfirm) - { - throw new UserFriendlyException(_localizer.GetString("Identity.PasswordConfirmationFailed").Value); - } - - await _profileAppService.ChangePasswordAsync( - new ChangePasswordInput() - { - CurrentPassword = ChangePasswordInfoModel.CurrentPassword, - NewPassword = ChangePasswordInfoModel.NewPassword - } - ); - - return NoContent(); - } - } - - public class ChangePasswordInfoModel - { - [Required] - [StringLength(IdentityUserConsts.MaxPasswordLength)] - [Display(Name = "DisplayName:CurrentPassword")] - [DataType(DataType.Password)] - public string CurrentPassword { get; set; } - - [Required] - [StringLength(IdentityUserConsts.MaxPasswordLength)] - [Display(Name = "DisplayName:NewPassword")] - [DataType(DataType.Password)] - public string NewPassword { get; set; } - - [Required] - [StringLength(IdentityUserConsts.MaxPasswordLength)] - [Display(Name = "DisplayName:NewPasswordConfirm")] - [DataType(DataType.Password)] - public string NewPasswordConfirm { get; set; } - } -} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/PersonalSettingsModal.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/PersonalSettingsModal.cshtml deleted file mode 100644 index 4c18be54eb..0000000000 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/PersonalSettingsModal.cshtml +++ /dev/null @@ -1,40 +0,0 @@ -@page -@using Microsoft.AspNetCore.Mvc.Localization -@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal -@using Volo.Abp.Identity.Localization -@using Volo.Abp.Identity.Settings -@using Volo.Abp.Identity.Web.Pages.Identity.Shared -@using Volo.Abp.Settings -@model PersonalSettingsModal -@inject IHtmlLocalizer L -@inject ISettingProvider SettingProvider -@{ - Layout = null; - var isUserNameUpdateEnabled = await SettingProvider.IsTrueAsync(IdentitySettingNames.User.IsUserNameUpdateEnabled); - var isEmailUpdateEnabled = await SettingProvider.IsTrueAsync(IdentitySettingNames.User.IsEmailUpdateEnabled); -} - -
- - - - - - - - - - - - - - - - - - - - - - -
\ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/change-password-modal.js b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/change-password-modal.js deleted file mode 100644 index c377ea718b..0000000000 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/change-password-modal.js +++ /dev/null @@ -1,18 +0,0 @@ -(function ($) { - - var l = abp.localization.getResource('AbpIdentity'); - var _changePasswordModal = new abp.ModalManager(abp.appPath + 'Identity/Shared/ChangePasswordModal'); - - $(function () { - - $("#abp-account-change-password").click(function (e) { - e.preventDefault(); - _changePasswordModal.open(); - }); - - _changePasswordModal.onResult(function () { - abp.message.success(l("PasswordChangedMessage")); - }); - }); - -})(jQuery); diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/personal-settings-modal.js b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/personal-settings-modal.js deleted file mode 100644 index 36cd526a29..0000000000 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/personal-settings-modal.js +++ /dev/null @@ -1,18 +0,0 @@ -(function ($) { - - var l = abp.localization.getResource('AbpIdentity'); - var _personalSettingsModal = new abp.ModalManager(abp.appPath + 'Identity/Shared/PersonalSettingsModal'); - - $(function () { - - $("#abp-account-personal-settings").click(function (e) { - e.preventDefault(); - _personalSettingsModal.open(); - }); - - _personalSettingsModal.onResult(function () { - //abp.message.success(l("PersonalSettingsSavedMessage")); - }); - }); - -})(jQuery); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/abstracts/toaster.ts b/npm/ng-packs/packages/theme-shared/src/lib/abstracts/toaster.ts index 57870ec620..5dbba869f1 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/abstracts/toaster.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/abstracts/toaster.ts @@ -10,6 +10,7 @@ export class AbstractToaster { sticky: boolean = false; constructor(protected messageService: MessageService) {} + info(message: string, title: string, options?: T): Observable { return this.show(message, title, 'info', options); } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts index d52b9faffc..c256510feb 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts @@ -1,10 +1,10 @@ import { StartLoader, StopLoader } from '@abp/ng.core'; -import { Component, Input, OnDestroy } from '@angular/core'; -import { NavigationEnd, NavigationStart, Router, NavigationError } from '@angular/router'; +import { ChangeDetectorRef, Component, Input, OnDestroy } from '@angular/core'; +import { NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router'; import { takeUntilDestroy } from '@ngx-validate/core'; import { Actions, ofActionSuccessful } from '@ngxs/store'; +import { interval, Subscription, timer } from 'rxjs'; import { filter } from 'rxjs/operators'; -import { timer } from 'rxjs'; @Component({ selector: 'abp-loader-bar', @@ -37,13 +37,15 @@ export class LoaderBarComponent implements OnDestroy { progressLevel: number = 0; - interval: any; + interval: Subscription; + + timer: Subscription; get boxShadow(): string { return `0 0 10px rgba(${this.color}, 0.5)`; } - constructor(private actions: Actions, private router: Router) { + constructor(private actions: Actions, private router: Router, private cdRef: ChangeDetectorRef) { actions .pipe( ofActionSuccessful(StartLoader, StopLoader), @@ -69,11 +71,15 @@ export class LoaderBarComponent implements OnDestroy { }); } - ngOnDestroy() {} + ngOnDestroy() { + this.interval.unsubscribe(); + } startLoading() { + if (this.isLoading || this.progressLevel !== 0) return; + this.isLoading = true; - const interval = setInterval(() => { + this.interval = interval(350).subscribe(() => { if (this.progressLevel < 75) { this.progressLevel += Math.random() * 10; } else if (this.progressLevel < 90) { @@ -81,18 +87,21 @@ export class LoaderBarComponent implements OnDestroy { } else if (this.progressLevel < 100) { this.progressLevel += 0.1; } else { - clearInterval(interval); + this.interval.unsubscribe(); } - }, 300); - - this.interval = interval; + this.cdRef.detectChanges(); + }); } stopLoading() { - clearInterval(this.interval); + this.interval.unsubscribe(); this.progressLevel = 100; this.isLoading = false; + if (this.timer) this.timer.unsubscribe(); - timer(810).subscribe(() => (this.progressLevel = 0)); + this.timer = timer(820).subscribe(() => { + this.progressLevel = 0; + this.cdRef.detectChanges(); + }); } } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/services/confirmation.service.ts b/npm/ng-packs/packages/theme-shared/src/lib/services/confirmation.service.ts index f0376dc038..f8338d95e8 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/services/confirmation.service.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/services/confirmation.service.ts @@ -1,10 +1,49 @@ import { Injectable } from '@angular/core'; import { AbstractToaster } from '../abstracts/toaster'; import { Confirmation } from '../models/confirmation'; +import { MessageService } from 'primeng/components/common/messageservice'; +import { fromEvent, Observable, Subject } from 'rxjs'; +import { takeUntil, debounceTime, filter } from 'rxjs/operators'; +import { Toaster } from '../models/toaster'; @Injectable({ providedIn: 'root' }) export class ConfirmationService extends AbstractToaster { key: string = 'abpConfirmation'; sticky: boolean = true; + + destroy$ = new Subject(); + + constructor(protected messageService: MessageService) { + super(messageService); + } + + show( + message: string, + title: string, + severity: Toaster.Severity, + options?: Confirmation.Options, + ): Observable { + this.listenToEscape(); + + return super.show(message, title, severity, options); + } + + clear(status?: Toaster.Status) { + super.clear(status); + + this.destroy$.next(); + } + + listenToEscape() { + fromEvent(document, 'keyup') + .pipe( + takeUntil(this.destroy$), + debounceTime(150), + filter((key: KeyboardEvent) => key && key.code === 'Escape'), + ) + .subscribe(_ => { + this.clear(); + }); + } } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj index b24cba6e60..871d25738b 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyCompanyName.MyProjectName.IdentityServer.csproj @@ -44,6 +44,7 @@ + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs index 9afb2e5263..fd8c86b5d2 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs @@ -12,6 +12,7 @@ using MyCompanyName.MyProjectName.Localization; using MyCompanyName.MyProjectName.MultiTenancy; using StackExchange.Redis; using Volo.Abp; +using Volo.Abp.Account; using Volo.Abp.Account.Web; using Volo.Abp.AspNetCore.Mvc.UI; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; @@ -32,6 +33,7 @@ namespace MyCompanyName.MyProjectName [DependsOn( typeof(AbpAutofacModule), typeof(AbpAccountWebIdentityServerModule), + typeof(AbpAccountApplicationModule), typeof(AbpAspNetCoreMvcUiBasicThemeModule), typeof(MyProjectNameEntityFrameworkCoreDbMigrationsModule) )] diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/Menus/MyProjectNameMenuContributor.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/Menus/MyProjectNameMenuContributor.cs index 17162b42c7..6a8b55292c 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/Menus/MyProjectNameMenuContributor.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/Menus/MyProjectNameMenuContributor.cs @@ -1,8 +1,11 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; using MyCompanyName.MyProjectName.Localization; using MyCompanyName.MyProjectName.MultiTenancy; +using Volo.Abp.Account.Localization; using Volo.Abp.TenantManagement.Web.Navigation; using Volo.Abp.UI.Navigation; @@ -10,6 +13,13 @@ namespace MyCompanyName.MyProjectName.Web.Menus { public class MyProjectNameMenuContributor : IMenuContributor { + private readonly IConfigurationRoot _configurationRoot; + + public MyProjectNameMenuContributor(IConfigurationRoot configurationRoot) + { + _configurationRoot = configurationRoot; + } + public async Task ConfigureMenuAsync(MenuConfigurationContext context) { if (context.Menu.Name == StandardMenus.Main) @@ -40,7 +50,11 @@ namespace MyCompanyName.MyProjectName.Web.Menus private Task ConfigureUserMenuAsync(MenuConfigurationContext context) { var l = context.ServiceProvider.GetRequiredService>(); + var accountStringLocalizer = context.ServiceProvider.GetRequiredService>(); + + var identityServerUrl = _configurationRoot["AuthServer:Authority"] ?? ""; + context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", accountStringLocalizer["ManageYourProfile"], $"{identityServerUrl.EnsureEndsWith('/')}Account/Manage", icon: "fa fa-cog", order: 1000, null, "_blank")); context.Menu.AddItem(new ApplicationMenuItem("Account.Logout", l["Logout"], url: "/Account/Logout", icon: "fa fa-power-off", order: int.MaxValue - 1000)); return Task.CompletedTask; diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs index f96d6cfc68..4f5bf7dd44 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs @@ -75,7 +75,8 @@ namespace MyCompanyName.MyProjectName.Web ConfigureAuthentication(context, configuration); ConfigureAutoMapper(); ConfigureVirtualFileSystem(hostingEnvironment); - ConfigureNavigationServices(); + ConfigureNavigationServices(configuration); + ConfigureSwaggerServices(context.Services); ConfigureMultiTenancy(); //Disabled swagger since it does not support ASP.NET Core 3.0 yet! @@ -168,11 +169,11 @@ namespace MyCompanyName.MyProjectName.Web } } - private void ConfigureNavigationServices() + private void ConfigureNavigationServices(IConfigurationRoot configuration) { Configure(options => { - options.MenuContributors.Add(new MyProjectNameMenuContributor()); + options.MenuContributors.Add(new MyProjectNameMenuContributor(configuration)); }); }