From f0b11b786c506b6fd8cf2e183ce33d94aa0bdd38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 11 Sep 2020 17:17:43 +0300 Subject: [PATCH] Implemented initial basic theme for the Blazor UI --- framework/Volo.Abp.sln | 7 + ...pNetCoreComponentsWebAssemblyBasicTheme.cs | 6 +- .../Pages/Authentication.razor | 2 +- .../Themes/Basic/LanguageSwitch.razor | 24 ++- .../Themes/Basic/LoginDisplay.razor | 19 +- .../Themes/Basic/MainLayout.razor | 37 ++-- .../Themes/Basic/NavMenu.razor | 38 +--- .../Themes/Basic/NavMenu.razor.cs | 27 +++ .../Themes/Basic/NavMenuItem.razor | 52 +++++ ...e.Components.WebAssembly.BasicTheme.csproj | 4 +- .../wwwroot/theme.css | 105 ++++++++++ .../wwwroot/theme.js | 16 ++ ...tCoreComponentsWebAssemblyThemingModule.cs | 17 ++ .../FodyWeavers.xml | 3 + .../FodyWeavers.xsd | 30 +++ ...Core.Components.WebAssembly.Theming.csproj | 17 ++ ...p.AspNetCore.Components.WebAssembly.csproj | 2 +- ...bpAspNetCoreComponentsWebAssemblyModule.cs | 15 +- .../AbpBlazorClientHttpMessageHandler.cs | 8 +- .../WebAssemblyCurrentPrincipalAccessor.cs | 31 ++- .../AbpIdentityBlazorAutoMapperProfile.cs | 6 + .../AbpIdentityBlazorModule.cs | 8 +- .../AbpIdentityWebMainMenuContributor.cs | 40 ++++ .../IdentityMenuNames.cs | 10 + .../Volo.Abp.Identity.Blazor.csproj | 1 - .../AbpPermissionManagementBlazorModule.cs | 6 +- ...olo.Abp.PermissionManagement.Blazor.csproj | 2 +- .../App.razor | 3 +- .../MyProjectNameBlazorModule.cs | 24 +-- .../MyProjectNameMenuContributor.cs | 15 ++ .../wwwroot/css/app.css | 185 ------------------ .../wwwroot/index.html | 5 +- .../wwwroot/main.css | 18 ++ 33 files changed, 487 insertions(+), 296 deletions(-) rename {templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor => framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme}/Pages/Authentication.razor (82%) create mode 100644 framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenuItem.razor create mode 100644 framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/wwwroot/theme.css create mode 100644 framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/wwwroot/theme.js create mode 100644 framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/AbpAspNetCoreComponentsWebAssemblyThemingModule.cs create mode 100644 framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/FodyWeavers.xml create mode 100644 framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/FodyWeavers.xsd create mode 100644 framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj rename templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/BlazorClientHttpMessageHandler.cs => framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs (84%) create mode 100644 modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityWebMainMenuContributor.cs create mode 100644 modules/identity/src/Volo.Abp.Identity.Blazor/IdentityMenuNames.cs create mode 100644 templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameMenuContributor.cs delete mode 100644 templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/css/app.css create mode 100644 templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/main.css diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index 4471b8664f..2ec7fce1d2 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -341,6 +341,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlazoriseUI", "src EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme", "src\Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme\Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj", "{ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Components.WebAssembly.Theming", "src\Volo.Abp.AspNetCore.Components.WebAssembly.Theming\Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj", "{29CA7471-4E3E-4E75-8B33-001DDF682F01}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1015,6 +1017,10 @@ Global {ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}.Debug|Any CPU.Build.0 = Debug|Any CPU {ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}.Release|Any CPU.ActiveCfg = Release|Any CPU {ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}.Release|Any CPU.Build.0 = Release|Any CPU + {29CA7471-4E3E-4E75-8B33-001DDF682F01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {29CA7471-4E3E-4E75-8B33-001DDF682F01}.Debug|Any CPU.Build.0 = Debug|Any CPU + {29CA7471-4E3E-4E75-8B33-001DDF682F01}.Release|Any CPU.ActiveCfg = Release|Any CPU + {29CA7471-4E3E-4E75-8B33-001DDF682F01}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1187,6 +1193,7 @@ Global {E1A62D10-F2FB-4040-BD60-11A3934058DF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {4EBDDB1B-D6C5-4FAE-B5A7-2171B18CDFA5} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {ABC27C10-C0FF-44CB-B4FF-A09C0B79F695} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {29CA7471-4E3E-4E75-8B33-001DDF682F01} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/AbpAspNetCoreComponentsWebAssemblyBasicTheme.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/AbpAspNetCoreComponentsWebAssemblyBasicTheme.cs index e3ba0ef70d..34511b291f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/AbpAspNetCoreComponentsWebAssemblyBasicTheme.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/AbpAspNetCoreComponentsWebAssemblyBasicTheme.cs @@ -1,12 +1,10 @@ -using Volo.Abp.BlazoriseUI; -using Volo.Abp.Http.Client.IdentityModel.WebAssembly; +using Volo.Abp.AspNetCore.Components.WebAssembly.Theming; using Volo.Abp.Modularity; namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme { [DependsOn( - typeof(AbpBlazoriseUIModule), - typeof(AbpHttpClientIdentityModelWebAssemblyModule) + typeof(AbpAspNetCoreComponentsWebAssemblyThemingModule) )] public class AbpAspNetCoreComponentsWebAssemblyBasicThemeModule : AbpModule { diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Pages/Authentication.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Pages/Authentication.razor similarity index 82% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Pages/Authentication.razor rename to framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Pages/Authentication.razor index ec9aa2f865..e237cea555 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Pages/Authentication.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Pages/Authentication.razor @@ -1,4 +1,4 @@ -@page "/authentication/{action}" +@page "/authentication/{action}" @using Microsoft.AspNetCore.Components.WebAssembly.Authentication diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor index 05c14e0a3f..8c7b348f7d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor @@ -1,28 +1,24 @@ @using Volo.Abp.Localization @using System.Globalization +@using System.Collections.Immutable @inject ILanguageProvider LanguageProvider @inject IJSRuntime JsRuntime -@if (_languages != null && _languages.Count > 1) +@if (_otherLanguages != null && _otherLanguages.Any()) { @_currentLanguage.DisplayName - @foreach (var language in _languages) + @foreach (var language in _otherLanguages) { - if (language == _currentLanguage) - { - continue; - } - @language.DisplayName } } @code { - private IReadOnlyList _languages; + private IReadOnlyList _otherLanguages; private LanguageInfo _currentLanguage; protected override async Task OnInitializedAsync() @@ -32,27 +28,29 @@ "Abp.SelectedLanguage" ); - _languages = await LanguageProvider.GetLanguagesAsync(); + _otherLanguages = await LanguageProvider.GetLanguagesAsync(); - if (!_languages.Any()) + if (!_otherLanguages.Any()) { return; } if (!selectedLanguageName.IsNullOrWhiteSpace()) { - _currentLanguage = _languages.FirstOrDefault(l => l.UiCultureName == selectedLanguageName); + _currentLanguage = _otherLanguages.FirstOrDefault(l => l.UiCultureName == selectedLanguageName); } if (_currentLanguage == null) { - _currentLanguage = _languages.FirstOrDefault(l => l.UiCultureName == CultureInfo.CurrentUICulture.Name); + _currentLanguage = _otherLanguages.FirstOrDefault(l => l.UiCultureName == CultureInfo.CurrentUICulture.Name); } if (_currentLanguage == null) { - _currentLanguage = _languages.FirstOrDefault(); + _currentLanguage = _otherLanguages.FirstOrDefault(); } + + _otherLanguages = _otherLanguages.Where(l => l != _currentLanguage).ToImmutableList(); } private async Task ChangeLanguageAsync(LanguageInfo language) 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 39e1dc3462..925783e16e 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 @@ -1,20 +1,25 @@ @using Microsoft.AspNetCore.Components.WebAssembly.Authentication - +@using Volo.Abp.Users +@inject ICurrentUser CurrentUser @inject NavigationManager Navigation @inject SignOutSessionStateManager SignOutManager - - Hello, @context.User.Identity.Name! - + + + @CurrentUser.UserName + + + Logout + + - Log in + Log in - @code{ - private async Task BeginSignOut(MouseEventArgs args) + private async Task BeginSignOut() { await SignOutManager.SetSignOutState(); Navigation.NavigateTo("authentication/logout"); diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor index 55822a06d7..ee08f7ef3b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor @@ -1,18 +1,29 @@ @inherits LayoutComponentBase @using Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic - - -
-
- - - About -
- -
- @Body + +
+ @Body
diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor index cff5563c29..e1ede1c0fd 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor @@ -1,37 +1,7 @@ - - -
- -
- -@code { - private bool collapseNavMenu = true; - - private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; - - private void ToggleNavMenu() +@if (Menu != null) +{ + foreach (var menuItem in Menu.Items) { - collapseNavMenu = !collapseNavMenu; + } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor.cs new file mode 100644 index 0000000000..e47603e163 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenu.razor.cs @@ -0,0 +1,27 @@ +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 NavMenu + { + [Inject] protected IMenuManager MenuManager { get; set; } + + protected ApplicationMenu Menu { get; set; } + + private bool collapseNavMenu = true; + + private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; + + protected override async Task OnInitializedAsync() + { + Menu = await MenuManager.GetAsync(StandardMenus.Main); + } + + private void ToggleNavMenu() + { + collapseNavMenu = !collapseNavMenu; + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenuItem.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenuItem.razor new file mode 100644 index 0000000000..8194896f61 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/NavMenuItem.razor @@ -0,0 +1,52 @@ +@using Volo.Abp.UI.Navigation +@{ + var elementId = MenuItem.ElementId ?? "MenuItem_" + MenuItem.Name.Replace(".", "_"); + var cssClass = string.IsNullOrEmpty(MenuItem.CssClass) ? string.Empty : MenuItem.CssClass; + var url = string.IsNullOrEmpty(MenuItem.Url) ? "#" : MenuItem.Url; +} +@if (MenuItem.IsLeaf) +{ + if (MenuItem.Url != null) + { + + } +} +else +{ + + +} +@code { + [Parameter] + public ApplicationMenuItem MenuItem { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj index ac88be9819..783af0b202 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj @@ -6,11 +6,11 @@ netstandard2.1 3.0 + Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme - - + diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/wwwroot/theme.css b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/wwwroot/theme.css new file mode 100644 index 0000000000..fc47596044 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/wwwroot/theme.css @@ -0,0 +1,105 @@ + +#main-navbar-tools a.dropdown-toggle { + text-decoration: none; + color: #fff; +} + +.navbar .dropdown-submenu { + position: relative; +} +.navbar .dropdown-menu { + margin: 0; + padding: 0; +} + .navbar .dropdown-menu a { + font-size: .9em; + padding: 10px 15px; + display: block; + min-width: 210px; + text-align: left; + border-radius: 0.25rem; + min-height: 44px; + } +.navbar .dropdown-submenu a::after { + transform: rotate(-90deg); + position: absolute; + right: 16px; + top: 18px; +} +.navbar .dropdown-submenu .dropdown-menu { + top: 0; + left: 100%; +} + +.card-header .btn { + padding: 2px 6px; +} +.card-header h5 { + margin: 0; +} +.container > .card { + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; +} + +@media screen and (min-width: 768px) { + .navbar .dropdown:hover > .dropdown-menu { + display: block; + } + + .navbar .dropdown-submenu:hover > .dropdown-menu { + display: block; + } +} +.input-validation-error { + border-color: #dc3545; +} +.field-validation-error { + font-size: 0.8em; +} + +.dataTables_scrollBody { + min-height: 248px; +} + +div.dataTables_wrapper div.dataTables_info { + padding-top: 11px; + white-space: nowrap; +} + +div.dataTables_wrapper div.dataTables_length label { + padding-top: 10px; + margin-bottom: 0; +} + +.rtl .dropdown-menu-right { + right: auto; + left: 0; +} + + .rtl .dropdown-menu-right a { + text-align: right; + } + +.rtl .navbar .dropdown-menu a { + text-align: right; +} +.rtl .navbar .dropdown-submenu .dropdown-menu { + top: 0; + left: auto; + right: 100%; +} + +/* TEMP */ + +.navbar-dark .navbar-nav .nav-link { + color: #000 !important; +} + +.navbar-nav > .nav-item > .nav-link, +.navbar-nav > .nav-item > .dropdown > .nav-link { + color: #fff !important; +} + +.navbar-nav>.nav-item>div>button{ + color:#fff; +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/wwwroot/theme.js b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/wwwroot/theme.js new file mode 100644 index 0000000000..8a5b94c7c6 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/wwwroot/theme.js @@ -0,0 +1,16 @@ +$(function () { + $('.dropdown-menu a.dropdown-toggle').on('click', function (e) { + if (!$(this).next().hasClass('show')) { + $(this).parents('.dropdown-menu').first().find('.show').removeClass("show"); + } + + var $subMenu = $(this).next(".dropdown-menu"); + $subMenu.toggleClass('show'); + + $(this).parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function (e) { + $('.dropdown-submenu .show').removeClass("show"); + }); + + return false; + }); +}); \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/AbpAspNetCoreComponentsWebAssemblyThemingModule.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/AbpAspNetCoreComponentsWebAssemblyThemingModule.cs new file mode 100644 index 0000000000..867e01467f --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/AbpAspNetCoreComponentsWebAssemblyThemingModule.cs @@ -0,0 +1,17 @@ +using Volo.Abp.BlazoriseUI; +using Volo.Abp.Http.Client.IdentityModel.WebAssembly; +using Volo.Abp.Modularity; +using Volo.Abp.UI.Navigation; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming +{ + [DependsOn( + typeof(AbpBlazoriseUIModule), + typeof(AbpHttpClientIdentityModelWebAssemblyModule), + typeof(AbpUiNavigationModule) + )] + public class AbpAspNetCoreComponentsWebAssemblyThemingModule : AbpModule + { + + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/FodyWeavers.xml b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/FodyWeavers.xml new file mode 100644 index 0000000000..00e1d9a1c1 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/FodyWeavers.xsd b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/FodyWeavers.xsd new file mode 100644 index 0000000000..3f3946e282 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/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/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj new file mode 100644 index 0000000000..86902f7038 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj @@ -0,0 +1,17 @@ + + + + + + + netstandard2.1 + 3.0 + + + + + + + + + diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo.Abp.AspNetCore.Components.WebAssembly.csproj b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo.Abp.AspNetCore.Components.WebAssembly.csproj index ceea6498c2..da0caaf2c9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo.Abp.AspNetCore.Components.WebAssembly.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo.Abp.AspNetCore.Components.WebAssembly.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs index f7e5c6375e..db6109e55a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs @@ -1,4 +1,6 @@ -using Volo.Abp.AspNetCore.Mvc.Client; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AspNetCore.Mvc.Client; +using Volo.Abp.Http.Client; using Volo.Abp.Modularity; using Volo.Abp.UI; @@ -10,6 +12,15 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly )] public class AbpAspNetCoreComponentsWebAssemblyModule : AbpModule { - + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(options => + { + options.ProxyClientBuildActions.Add((_, builder) => + { + builder.AddHttpMessageHandler(); + }); + }); + } } } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/BlazorClientHttpMessageHandler.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs similarity index 84% rename from templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/BlazorClientHttpMessageHandler.cs rename to framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs index 8c96325b6d..7d59042806 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/BlazorClientHttpMessageHandler.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpBlazorClientHttpMessageHandler.cs @@ -6,13 +6,13 @@ using System.Threading.Tasks; using Microsoft.JSInterop; using Volo.Abp.DependencyInjection; -namespace MyCompanyName.MyProjectName.Blazor +namespace Volo.Abp.AspNetCore.Components.WebAssembly { - public class BlazorClientHttpMessageHandler : DelegatingHandler, ITransientDependency + public class AbpBlazorClientHttpMessageHandler : DelegatingHandler, ITransientDependency { private readonly IJSRuntime _jsRuntime; - public BlazorClientHttpMessageHandler(IJSRuntime jsRuntime) + public AbpBlazorClientHttpMessageHandler(IJSRuntime jsRuntime) { _jsRuntime = jsRuntime; } @@ -39,4 +39,4 @@ namespace MyCompanyName.MyProjectName.Blazor } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentPrincipalAccessor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentPrincipalAccessor.cs index 675f01196d..308fb28659 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentPrincipalAccessor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentPrincipalAccessor.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Security.Claims; using Volo.Abp.AspNetCore.Mvc.Client; using Volo.Abp.DependencyInjection; @@ -10,23 +11,37 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly { protected ICachedApplicationConfigurationClient ConfigurationClient { get; } - public WebAssemblyCurrentPrincipalAccessor(ICachedApplicationConfigurationClient configurationClient) + public WebAssemblyCurrentPrincipalAccessor( + ICachedApplicationConfigurationClient configurationClient) { ConfigurationClient = configurationClient; } protected override ClaimsPrincipal GetClaimsPrincipal() { - //TODO: Should be optimized! Or should be replaced? - var configuration = ConfigurationClient.Get(); var claims = new List(); - claims.Add(new Claim(AbpClaimTypes.UserName,configuration.CurrentUser.UserName)); - claims.Add(new Claim(AbpClaimTypes.Email,configuration.CurrentUser.Email)); - claims.Add(new Claim(AbpClaimTypes.UserId,configuration.CurrentUser.Id.ToString())); - claims.Add(new Claim(AbpClaimTypes.TenantId,configuration.CurrentUser.TenantId.ToString())); + if (!configuration.CurrentUser.UserName.IsNullOrWhiteSpace()) + { + claims.Add(new Claim(AbpClaimTypes.UserName,configuration.CurrentUser.UserName)); + } + + if (!configuration.CurrentUser.Email.IsNullOrWhiteSpace()) + { + claims.Add(new Claim(AbpClaimTypes.Email,configuration.CurrentUser.Email)); + } + + if (configuration.CurrentUser.Id != null) + { + claims.Add(new Claim(AbpClaimTypes.UserId,configuration.CurrentUser.Id.ToString())); + } + + if (configuration.CurrentUser.TenantId != null) + { + claims.Add(new Claim(AbpClaimTypes.TenantId,configuration.CurrentUser.TenantId.ToString())); + } foreach (var role in configuration.CurrentUser.Roles) { diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorAutoMapperProfile.cs b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorAutoMapperProfile.cs index f4f111df41..d37ee863ba 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorAutoMapperProfile.cs +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorAutoMapperProfile.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Volo.Abp.AutoMapper; namespace Volo.Abp.Identity.Blazor { @@ -8,6 +9,11 @@ namespace Volo.Abp.Identity.Blazor { CreateMap() .MapExtraProperties(); + + CreateMap() + .Ignore(x => x.Password) + .Ignore(x => x.RoleNames) + .MapExtraProperties(); } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorModule.cs b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorModule.cs index 364f57bb36..fcf7d69b0e 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityBlazorModule.cs @@ -1,14 +1,13 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AutoMapper; using Volo.Abp.Modularity; -using Volo.Abp.BlazoriseUI; using Volo.Abp.PermissionManagement.Blazor; +using Volo.Abp.UI.Navigation; namespace Volo.Abp.Identity.Blazor { [DependsOn( typeof(AbpIdentityHttpApiClientModule), - typeof(AbpBlazoriseUIModule), typeof(AbpAutoMapperModule), typeof(AbpPermissionManagementBlazorModule) )] @@ -22,6 +21,11 @@ namespace Volo.Abp.Identity.Blazor { options.AddProfile(validate: true); }); + + Configure(options => + { + options.MenuContributors.Add(new AbpIdentityWebMainMenuContributor()); + }); } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityWebMainMenuContributor.cs b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityWebMainMenuContributor.cs new file mode 100644 index 0000000000..17c956f0c7 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/AbpIdentityWebMainMenuContributor.cs @@ -0,0 +1,40 @@ +using System.Threading.Tasks; +using Volo.Abp.Identity.Localization; +using Volo.Abp.UI.Navigation; + +namespace Volo.Abp.Identity.Blazor +{ + public class AbpIdentityWebMainMenuContributor : IMenuContributor + { + public virtual async Task ConfigureMenuAsync(MenuConfigurationContext context) + { + if (context.Menu.Name != StandardMenus.Main) + { + return; + } + + var hasRolePermission = await context.IsGrantedAsync(IdentityPermissions.Roles.Default); + var hasUserPermission = await context.IsGrantedAsync(IdentityPermissions.Users.Default); + + if (hasRolePermission || hasUserPermission) + { + var administrationMenu = context.Menu.GetAdministration(); + + var l = context.GetLocalizer(); + + var identityMenuItem = new ApplicationMenuItem(IdentityMenuNames.GroupName, l["Menu:IdentityManagement"], icon: "fa fa-id-card-o"); + administrationMenu.AddItem(identityMenuItem); + + if (hasRolePermission) + { + identityMenuItem.AddItem(new ApplicationMenuItem(IdentityMenuNames.Roles, l["Roles"], url: "/identity/roles")); + } + + if (hasUserPermission) + { + identityMenuItem.AddItem(new ApplicationMenuItem(IdentityMenuNames.Users, l["Users"], url: "/identity/users")); + } + } + } + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/IdentityMenuNames.cs b/modules/identity/src/Volo.Abp.Identity.Blazor/IdentityMenuNames.cs new file mode 100644 index 0000000000..9cd5b1dc37 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/IdentityMenuNames.cs @@ -0,0 +1,10 @@ +namespace Volo.Abp.Identity.Blazor +{ + public class IdentityMenuNames + { + public const string GroupName = "AbpIdentity"; + + public const string Roles = GroupName + ".Roles"; + public const string Users = GroupName + ".Users"; + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Blazor/Volo.Abp.Identity.Blazor.csproj b/modules/identity/src/Volo.Abp.Identity.Blazor/Volo.Abp.Identity.Blazor.csproj index 867ce9aaed..19bfb3831c 100644 --- a/modules/identity/src/Volo.Abp.Identity.Blazor/Volo.Abp.Identity.Blazor.csproj +++ b/modules/identity/src/Volo.Abp.Identity.Blazor/Volo.Abp.Identity.Blazor.csproj @@ -9,7 +9,6 @@ - diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/AbpPermissionManagementBlazorModule.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/AbpPermissionManagementBlazorModule.cs index 5fc1c56f82..26381615f3 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/AbpPermissionManagementBlazorModule.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/AbpPermissionManagementBlazorModule.cs @@ -1,11 +1,11 @@ -using Volo.Abp.AutoMapper; -using Volo.Abp.BlazoriseUI; +using Volo.Abp.AspNetCore.Components.WebAssembly.Theming; +using Volo.Abp.AutoMapper; using Volo.Abp.Modularity; namespace Volo.Abp.PermissionManagement.Blazor { [DependsOn( - typeof(AbpBlazoriseUIModule), + typeof(AbpAspNetCoreComponentsWebAssemblyThemingModule), typeof(AbpAutoMapperModule), typeof(AbpPermissionManagementHttpApiClientModule) )] diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Volo.Abp.PermissionManagement.Blazor.csproj b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Volo.Abp.PermissionManagement.Blazor.csproj index a2da9c1f95..0663ca49a5 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Volo.Abp.PermissionManagement.Blazor.csproj +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Volo.Abp.PermissionManagement.Blazor.csproj @@ -9,7 +9,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/App.razor b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/App.razor index 0c90610aef..2ec255119b 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/App.razor +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/App.razor @@ -1,8 +1,9 @@ @using Volo.Abp.Identity.Blazor +@using Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme @using Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic + AdditionalAssemblies="new []{ typeof(AbpIdentityBlazorModule).Assembly, typeof(AbpAspNetCoreComponentsWebAssemblyBasicThemeModule).Assembly }"> diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs index e2bf94fcaa..4edf499972 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs @@ -8,30 +8,21 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Volo.Abp; using Volo.Abp.Autofac; -using Volo.Abp.Http.Client; using Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme; using Volo.Abp.Modularity; +using Volo.Abp.UI.Navigation; +using Volo.Abp.Identity.Blazor; namespace MyCompanyName.MyProjectName.Blazor { [DependsOn( typeof(AbpAutofacModule), typeof(MyProjectNameHttpApiClientModule), + typeof(AbpIdentityBlazorModule), typeof(AbpAspNetCoreComponentsWebAssemblyBasicThemeModule) )] public class MyProjectNameBlazorModule : AbpModule { - public override void PreConfigureServices(ServiceConfigurationContext context) - { - PreConfigure(options => - { - options.ProxyClientBuildActions.Add((_, builder) => - { - builder.AddHttpMessageHandler(); - }); - }); - } - public override void ConfigureServices(ServiceConfigurationContext context) { var environment = context.Services.GetSingletonInstance(); @@ -41,6 +32,15 @@ namespace MyCompanyName.MyProjectName.Blazor ConfigureHttpClient(context, environment); ConfigureBlazorise(context); ConfigureUI(builder); + ConfigureMenu(context); + } + + private void ConfigureMenu(ServiceConfigurationContext context) + { + Configure(options => + { + options.MenuContributors.Add(new MyProjectNameMenuContributor()); + }); } private void ConfigureBlazorise(ServiceConfigurationContext context) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameMenuContributor.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameMenuContributor.cs new file mode 100644 index 0000000000..59a73c6b17 --- /dev/null +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyProjectNameMenuContributor.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Volo.Abp.UI.Navigation; + +namespace MyCompanyName.MyProjectName.Blazor +{ + public class MyProjectNameMenuContributor : IMenuContributor + { + public Task ConfigureMenuAsync(MenuConfigurationContext context) + { + context.Menu.AddItem(new ApplicationMenuItem("Test", "Test", "/test")); + + return Task.CompletedTask; + } + } +} diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/css/app.css b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/css/app.css deleted file mode 100644 index c3830ee9f1..0000000000 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/css/app.css +++ /dev/null @@ -1,185 +0,0 @@ -html, body { - font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; -} - -a, .btn-link { - color: #0366d6; -} - -.btn-primary { - color: #fff; - background-color: #1b6ec2; - border-color: #1861ac; -} - -app { - position: relative; - display: flex; - flex-direction: column; -} - -.top-row { - height: 3.5rem; - display: flex; - align-items: center; -} - -.main { - flex: 1; -} - - .main .top-row { - background-color: #f7f7f7; - border-bottom: 1px solid #d6d5d5; - justify-content: flex-end; - } - - .main .top-row > a, .main .top-row .btn-link { - white-space: nowrap; - margin-left: 1.5rem; - } - - .main .top-row a:first-child { - overflow: hidden; - text-overflow: ellipsis; - } - -.sidebar { - background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); -} - - .sidebar .top-row { - background-color: rgba(0,0,0,0.4); - } - - .sidebar .navbar-brand { - font-size: 1.1rem; - } - - .sidebar .oi { - width: 2rem; - font-size: 1.1rem; - vertical-align: text-top; - top: -2px; - } - - .sidebar .nav-item { - font-size: 0.9rem; - padding-bottom: 0.5rem; - } - - .sidebar .nav-item:first-of-type { - padding-top: 1rem; - } - - .sidebar .nav-item:last-of-type { - padding-bottom: 1rem; - } - - .sidebar .nav-item a { - color: #d7d7d7; - border-radius: 4px; - height: 3rem; - display: flex; - align-items: center; - line-height: 3rem; - } - - .sidebar .nav-item a.active { - background-color: rgba(255,255,255,0.25); - color: white; - } - - .sidebar .nav-item a:hover { - background-color: rgba(255,255,255,0.1); - color: white; - } - -.content { - padding-top: 1.1rem; -} - -.navbar-toggler { - background-color: rgba(255, 255, 255, 0.1); -} - -.valid.modified:not([type=checkbox]) { - outline: 1px solid #26b050; -} - -.invalid { - outline: 1px solid red; -} - -.validation-message { - color: red; -} - -#blazor-error-ui { - background: lightyellow; - bottom: 0; - box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); - display: none; - left: 0; - padding: 0.6rem 1.25rem 0.7rem 1.25rem; - position: fixed; - width: 100%; - z-index: 1000; -} - - #blazor-error-ui .dismiss { - cursor: pointer; - position: absolute; - right: 0.75rem; - top: 0.5rem; - } - -.nav .nav-item .nav-link i { - margin: 5px; -} - -@media (max-width: 767.98px) { - .main .top-row:not(.auth) { - display: none; - } - - .main .top-row.auth { - justify-content: space-between; - } - - .main .top-row a, .main .top-row .btn-link { - margin-left: 0; - } -} - -@media (min-width: 768px) { - app { - flex-direction: row; - } - - .sidebar { - width: 250px; - height: 100vh; - position: sticky; - top: 0; - } - - .main .top-row { - position: sticky; - top: 0; - } - - .main > div { - padding-left: 2rem !important; - padding-right: 1.5rem !important; - } - - .navbar-toggler { - display: none; - } - - .sidebar .collapse { - /* Never collapse the sidebar for wide screens */ - display: block; - } -} diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/index.html b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/index.html index ade028b137..99ab025095 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/index.html +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/index.html @@ -12,8 +12,8 @@ - - + + @@ -33,6 +33,7 @@ + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/main.css b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/main.css new file mode 100644 index 0000000000..23e0f7a249 --- /dev/null +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/main.css @@ -0,0 +1,18 @@ +#blazor-error-ui { + background: lightyellow; + bottom: 0; + box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); + display: none; + left: 0; + padding: 0.6rem 1.25rem 0.7rem 1.25rem; + position: fixed; + width: 100%; + z-index: 1000; +} + +#blazor-error-ui .dismiss { + cursor: pointer; + position: absolute; + right: 0.75rem; + top: 0.5rem; +} \ No newline at end of file