mirror of https://github.com/abpframework/abp.git
156 changed files with 3740 additions and 219 deletions
@ -0,0 +1,20 @@ |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming; |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAspNetCoreComponentsWebAssemblyThemingModule) |
|||
)] |
|||
public class AbpAspNetCoreComponentsWebAssemblyBasicThemeModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpRouterOptions>(options => |
|||
{ |
|||
options.AdditionalAssemblies.Add(typeof(AbpAspNetCoreComponentsWebAssemblyBasicThemeModule).Assembly); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,7 @@ |
|||
@page "/authentication/{action}" |
|||
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication |
|||
<RemoteAuthenticatorView Action="@Action" /> |
|||
|
|||
@code{ |
|||
[Parameter] public string Action { get; set; } |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
@using Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing |
|||
@using Microsoft.Extensions.Options |
|||
@inject IOptions<AbpRouterOptions> RouterOptions |
|||
<CascadingAuthenticationState> |
|||
<Router AppAssembly="RouterOptions.Value.AppAssembly" |
|||
AdditionalAssemblies="RouterOptions.Value.AdditionalAssemblies"> |
|||
<Found Context="routeData"> |
|||
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"> |
|||
<NotAuthorized> |
|||
@if (!context.User.Identity.IsAuthenticated) |
|||
{ |
|||
<RedirectToLogin /> |
|||
} |
|||
else |
|||
{ |
|||
<p>You are not authorized to access this resource.</p> |
|||
} |
|||
</NotAuthorized> |
|||
</AuthorizeRouteView> |
|||
</Found> |
|||
<NotFound> |
|||
<LayoutView Layout="@typeof(MainLayout)"> |
|||
<p>Sorry, there's nothing at this address.</p> |
|||
</LayoutView> |
|||
</NotFound> |
|||
</Router> |
|||
</CascadingAuthenticationState> |
|||
@ -0,0 +1,65 @@ |
|||
@using Volo.Abp.Localization |
|||
@using System.Globalization |
|||
@using System.Collections.Immutable |
|||
@inject ILanguageProvider LanguageProvider |
|||
@inject IJSRuntime JsRuntime |
|||
@if (_otherLanguages != null && _otherLanguages.Any()) |
|||
{ |
|||
<Dropdown> |
|||
<DropdownToggle Color="Color.None"> |
|||
@_currentLanguage.DisplayName |
|||
</DropdownToggle> |
|||
<DropdownMenu> |
|||
@foreach (var language in _otherLanguages) |
|||
{ |
|||
<DropdownItem Clicked="() => ChangeLanguageAsync(language)">@language.DisplayName</DropdownItem> |
|||
} |
|||
</DropdownMenu> |
|||
</Dropdown> |
|||
} |
|||
@code { |
|||
private IReadOnlyList<LanguageInfo> _otherLanguages; |
|||
private LanguageInfo _currentLanguage; |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
var selectedLanguageName = await JsRuntime.InvokeAsync<string>( |
|||
"localStorage.getItem", |
|||
"Abp.SelectedLanguage" |
|||
); |
|||
|
|||
_otherLanguages = await LanguageProvider.GetLanguagesAsync(); |
|||
|
|||
if (!_otherLanguages.Any()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (!selectedLanguageName.IsNullOrWhiteSpace()) |
|||
{ |
|||
_currentLanguage = _otherLanguages.FirstOrDefault(l => l.UiCultureName == selectedLanguageName); |
|||
} |
|||
|
|||
if (_currentLanguage == null) |
|||
{ |
|||
_currentLanguage = _otherLanguages.FirstOrDefault(l => l.UiCultureName == CultureInfo.CurrentUICulture.Name); |
|||
} |
|||
|
|||
if (_currentLanguage == null) |
|||
{ |
|||
_currentLanguage = _otherLanguages.FirstOrDefault(); |
|||
} |
|||
|
|||
_otherLanguages = _otherLanguages.Where(l => l != _currentLanguage).ToImmutableList(); |
|||
} |
|||
|
|||
private async Task ChangeLanguageAsync(LanguageInfo language) |
|||
{ |
|||
await JsRuntime.InvokeVoidAsync( |
|||
"localStorage.setItem", |
|||
"Abp.SelectedLanguage", language.UiCultureName |
|||
); |
|||
|
|||
await JsRuntime.InvokeVoidAsync("location.reload"); |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication |
|||
@using Volo.Abp.Users |
|||
@inject ICurrentUser CurrentUser |
|||
@inject NavigationManager Navigation |
|||
@inject SignOutSessionStateManager SignOutManager |
|||
<AuthorizeView> |
|||
<Authorized> |
|||
<Dropdown> |
|||
<DropdownToggle Color="Color.None"> |
|||
@CurrentUser.UserName |
|||
</DropdownToggle> |
|||
<DropdownMenu> |
|||
<DropdownItem Clicked="BeginSignOut">Logout</DropdownItem> |
|||
</DropdownMenu> |
|||
</Dropdown> |
|||
</Authorized> |
|||
<NotAuthorized> |
|||
<a class="nav-link" href="authentication/login">Log in</a> |
|||
</NotAuthorized> |
|||
</AuthorizeView> |
|||
@code{ |
|||
private async Task BeginSignOut() |
|||
{ |
|||
await SignOutManager.SetSignOutState(); |
|||
Navigation.NavigateTo("authentication/logout"); |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
@inherits LayoutComponentBase |
|||
@using Volo.Abp.Ui.Branding |
|||
@inject IBrandingProvider BrandingProvider |
|||
<nav class="navbar navbar-expand-md navbar-dark bg-dark shadow-sm flex-column flex-md-row mb-4" id="main-navbar" style="min-height: 4rem;"> |
|||
<div class="container"> |
|||
<a class="navbar-brand" href="/">@BrandingProvider.AppName</a> |
|||
<button class="navbar-toggler" type="button" data-toggle="collapse" |
|||
data-target="#main-navbar-collapse" aria-controls="main-navbar-collapse" |
|||
aria-expanded="false" aria-label="Toggle navigation"> |
|||
<span class="navbar-toggler-icon"></span> |
|||
</button> |
|||
<div class="collapse navbar-collapse" id="main-navbar-collapse"> |
|||
<ul class="navbar-nav mx-auto"> |
|||
<NavMenu/> |
|||
</ul> |
|||
<ul class="navbar-nav"> |
|||
<li class="nav-item"> |
|||
<LanguageSwitch/> |
|||
</li> |
|||
<li class="nav-item"> |
|||
<LoginDisplay/> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</nav> |
|||
<div class="container"> |
|||
@Body |
|||
</div> |
|||
@ -0,0 +1,7 @@ |
|||
@if (Menu != null) |
|||
{ |
|||
foreach (var menuItem in Menu.Items) |
|||
{ |
|||
<NavMenuItem MenuItem="@menuItem" /> |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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) |
|||
{ |
|||
<li class="nav-item @cssClass" disabled="@MenuItem.IsDisabled"> |
|||
<NavLink class="nav-link" href="@url" id="@elementId"> |
|||
@if (MenuItem.Icon != null) |
|||
{ |
|||
if (MenuItem.Icon.StartsWith("fa")) |
|||
{ |
|||
<i class="@MenuItem.Icon"></i> |
|||
} |
|||
} |
|||
@MenuItem.DisplayName |
|||
</NavLink> |
|||
</li> |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
<li class="nav-item"> |
|||
<div class="dropdown"> |
|||
<a class="nav-link dropdown-toggle" href="#" id="@elementId" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
|||
@if (MenuItem.Icon != null) |
|||
{ |
|||
if (MenuItem.Icon.StartsWith("fa")) |
|||
{ |
|||
<i class="@MenuItem.Icon"></i> |
|||
} |
|||
} |
|||
@MenuItem.DisplayName |
|||
</a> |
|||
<div class="dropdown-menu border-0 shadow-sm" aria-labelledby="@elementId"> |
|||
@foreach (var childMenuItem in MenuItem.Items) |
|||
{ |
|||
<NavMenuItem MenuItem="@childMenuItem" /> |
|||
} |
|||
</div> |
|||
</div> |
|||
</li> |
|||
|
|||
} |
|||
@code { |
|||
[Parameter] |
|||
public ApplicationMenuItem MenuItem { get; set; } |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
@inject NavigationManager Navigation |
|||
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication |
|||
@code { |
|||
protected override void OnInitialized() |
|||
{ |
|||
Navigation.NavigateTo($"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}"); |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
@using System.Net.Http |
|||
@using Microsoft.AspNetCore.Components.Authorization |
|||
@using Microsoft.AspNetCore.Components.Forms |
|||
@using Microsoft.AspNetCore.Components.Routing |
|||
@using Microsoft.AspNetCore.Components.Web |
|||
@using Microsoft.AspNetCore.Components.WebAssembly.Http |
|||
@using Microsoft.JSInterop |
|||
@using Volo.Abp.AspNetCore.Components.WebAssembly |
|||
@using Blazorise |
|||
@using Blazorise.DataGrid |
|||
@ -0,0 +1,16 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Razor"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<RazorLangVersion>3.0</RazorLangVersion> |
|||
<PackageId>Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme</PackageId> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.WebAssembly.Theming\Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -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; |
|||
} |
|||
@ -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; |
|||
}); |
|||
}); |
|||
@ -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 |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,16 @@ |
|||
using System.Reflection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing |
|||
{ |
|||
public class AbpRouterOptions |
|||
{ |
|||
public Assembly AppAssembly { get; set; } |
|||
|
|||
public RouterAssemblyList AdditionalAssemblies { get; } |
|||
|
|||
public AbpRouterOptions() |
|||
{ |
|||
AdditionalAssemblies = new RouterAssemblyList(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System.Collections.Generic; |
|||
using System.Reflection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing |
|||
{ |
|||
public class RouterAssemblyList : List<Assembly> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Razor"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<RazorLangVersion>3.0</RazorLangVersion> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.BlazoriseUI\Volo.Abp.BlazoriseUI.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Http.Client.IdentityModel.WebAssembly\Volo.Abp.Http.Client.IdentityModel.WebAssembly.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.UI.Navigation\Volo.Abp.UI.Navigation.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,51 @@ |
|||
using System; |
|||
using System.Reflection; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp; |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly; |
|||
using Volo.Abp.AspNetCore.Mvc.Client; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting |
|||
{ |
|||
public static class AbpWebAssemblyHostBuilderExtensions |
|||
{ |
|||
public static IAbpApplicationWithExternalServiceProvider AddApplication<TStartupModule>( |
|||
[NotNull] this WebAssemblyHostBuilder builder, |
|||
Action<AbpWebAssemblyApplicationCreationOptions> options) |
|||
where TStartupModule : IAbpModule |
|||
{ |
|||
Check.NotNull(builder, nameof(builder)); |
|||
|
|||
builder.Services.AddSingleton<IConfiguration>(builder.Configuration); |
|||
builder.Services.AddSingleton(builder); |
|||
|
|||
var application = builder.Services.AddApplication<TStartupModule>(opts => |
|||
{ |
|||
options?.Invoke(new AbpWebAssemblyApplicationCreationOptions(builder, opts)); |
|||
}); |
|||
|
|||
return application; |
|||
} |
|||
|
|||
public static async Task InitializeAsync( |
|||
[NotNull] this IAbpApplicationWithExternalServiceProvider application, |
|||
[NotNull] IServiceProvider serviceProvider) |
|||
{ |
|||
Check.NotNull(application, nameof(application)); |
|||
Check.NotNull(serviceProvider, nameof(serviceProvider)); |
|||
|
|||
application.Initialize(serviceProvider); |
|||
|
|||
using (var scope = serviceProvider.CreateScope()) |
|||
{ |
|||
await scope.ServiceProvider |
|||
.GetRequiredService<ICachedApplicationConfigurationClient>() |
|||
.InitializeAsync(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<AssemblyName>Volo.Abp.AspNetCore.Components.WebAssembly</AssemblyName> |
|||
<PackageId>Volo.Abp.AspNetCore.Components.WebAssembly</PackageId> |
|||
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.Client.Common\Volo.Abp.AspNetCore.Mvc.Client.Common.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.UI\Volo.Abp.UI.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.1" /> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="3.1.6" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,26 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.AspNetCore.Mvc.Client; |
|||
using Volo.Abp.Http.Client; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.UI; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAspNetCoreMvcClientCommonModule), |
|||
typeof(AbpUiModule) |
|||
)] |
|||
public class AbpAspNetCoreComponentsWebAssemblyModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
PreConfigure<AbpHttpClientBuilderOptions>(options => |
|||
{ |
|||
options.ProxyClientBuildActions.Add((_, builder) => |
|||
{ |
|||
builder.AddHttpMessageHandler<AbpBlazorClientHttpMessageHandler>(); |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
using System; |
|||
using System.Net.Http; |
|||
using System.Net.Http.Headers; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.JSInterop; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public class AbpBlazorClientHttpMessageHandler : DelegatingHandler, ITransientDependency |
|||
{ |
|||
private readonly IJSRuntime _jsRuntime; |
|||
|
|||
public AbpBlazorClientHttpMessageHandler(IJSRuntime jsRuntime) |
|||
{ |
|||
_jsRuntime = jsRuntime; |
|||
} |
|||
|
|||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) |
|||
{ |
|||
await SetLanguageAsync(request, cancellationToken); |
|||
|
|||
return await base.SendAsync(request, cancellationToken); |
|||
} |
|||
|
|||
private async Task SetLanguageAsync(HttpRequestMessage request, CancellationToken cancellationToken) |
|||
{ |
|||
var selectedLanguage = await _jsRuntime.InvokeAsync<string>( |
|||
"localStorage.getItem", |
|||
cancellationToken, |
|||
"Abp.SelectedLanguage" |
|||
); |
|||
|
|||
if (!selectedLanguage.IsNullOrWhiteSpace()) |
|||
{ |
|||
request.Headers.AcceptLanguage.Clear(); |
|||
request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(selectedLanguage)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public class AbpWebAssemblyApplicationCreationOptions |
|||
{ |
|||
public WebAssemblyHostBuilder HostBuilder { get; } |
|||
|
|||
public AbpApplicationCreationOptions ApplicationCreationOptions { get; } |
|||
|
|||
public AbpWebAssemblyApplicationCreationOptions( |
|||
WebAssemblyHostBuilder hostBuilder, |
|||
AbpApplicationCreationOptions applicationCreationOptions) |
|||
{ |
|||
HostBuilder = hostBuilder; |
|||
ApplicationCreationOptions = applicationCreationOptions; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public class ApplicationConfigurationCache : ISingletonDependency |
|||
{ |
|||
protected ApplicationConfigurationDto Configuration { get; set; } |
|||
|
|||
public virtual ApplicationConfigurationDto Get() |
|||
{ |
|||
return Configuration; |
|||
} |
|||
|
|||
internal void Set(ApplicationConfigurationDto configuration) |
|||
{ |
|||
Configuration = configuration; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public interface IUiMessageService |
|||
{ |
|||
Task<bool> ConfirmAsync(string message, string title = null); |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.JSInterop; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public class UiMessageService : IUiMessageService, ITransientDependency |
|||
{ |
|||
protected IJSRuntime JsRuntime { get; } |
|||
|
|||
public UiMessageService(IJSRuntime jsRuntime) |
|||
{ |
|||
JsRuntime = jsRuntime; |
|||
} |
|||
|
|||
public async Task<bool> ConfirmAsync(string message, string title = null) |
|||
{ |
|||
//TODO: Implement with sweetalert in a new package
|
|||
return await JsRuntime.InvokeAsync<bool>("confirm", message); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; |
|||
using Volo.Abp.AspNetCore.Mvc.Client; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Http.Client.DynamicProxying; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public class WebAssemblyCachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency |
|||
{ |
|||
protected IHttpClientProxy<IAbpApplicationConfigurationAppService> Proxy { get; } |
|||
|
|||
protected ApplicationConfigurationCache Cache { get; } |
|||
|
|||
public WebAssemblyCachedApplicationConfigurationClient( |
|||
IHttpClientProxy<IAbpApplicationConfigurationAppService> proxy, |
|||
ApplicationConfigurationCache cache) |
|||
{ |
|||
Proxy = proxy; |
|||
Cache = cache; |
|||
} |
|||
|
|||
public virtual async Task InitializeAsync() |
|||
{ |
|||
Cache.Set(await Proxy.Service.GetAsync()); |
|||
} |
|||
|
|||
public virtual Task<ApplicationConfigurationDto> GetAsync() |
|||
{ |
|||
return Task.FromResult(GetConfigurationByChecking()); |
|||
} |
|||
|
|||
public virtual ApplicationConfigurationDto Get() |
|||
{ |
|||
return GetConfigurationByChecking(); |
|||
} |
|||
|
|||
private ApplicationConfigurationDto GetConfigurationByChecking() |
|||
{ |
|||
var configuration = Cache.Get(); |
|||
if (configuration == null) |
|||
{ |
|||
throw new AbpException( |
|||
$"{nameof(WebAssemblyCachedApplicationConfigurationClient)} should be initialized before using it."); |
|||
} |
|||
|
|||
return configuration; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Security.Claims; |
|||
using Volo.Abp.AspNetCore.Mvc.Client; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Security.Claims; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public class WebAssemblyCurrentPrincipalAccessor : CurrentPrincipalAccessorBase, ITransientDependency |
|||
{ |
|||
protected ICachedApplicationConfigurationClient ConfigurationClient { get; } |
|||
|
|||
public WebAssemblyCurrentPrincipalAccessor( |
|||
ICachedApplicationConfigurationClient configurationClient) |
|||
{ |
|||
ConfigurationClient = configurationClient; |
|||
} |
|||
|
|||
protected override ClaimsPrincipal GetClaimsPrincipal() |
|||
{ |
|||
var configuration = ConfigurationClient.Get(); |
|||
|
|||
var claims = new List<Claim>(); |
|||
|
|||
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())); |
|||
} |
|||
else if (configuration.CurrentTenant.Id != null) |
|||
{ |
|||
claims.Add(new Claim(AbpClaimTypes.TenantId,configuration.CurrentTenant.Id.ToString())); |
|||
} |
|||
|
|||
foreach (var role in configuration.CurrentUser.Roles) |
|||
{ |
|||
claims.Add(new Claim(AbpClaimTypes.Role, role)); |
|||
} |
|||
|
|||
return new ClaimsPrincipal(new ClaimsIdentity(claims)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,69 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.AspNetCore.Mvc.MultiTenancy; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Http.Client.DynamicProxying; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Components.WebAssembly |
|||
{ |
|||
public class WebAssemblyRemoteTenantStore : ITenantStore, ITransientDependency |
|||
{ |
|||
protected IHttpClientProxy<IAbpTenantAppService> Proxy { get; } |
|||
|
|||
public WebAssemblyRemoteTenantStore( |
|||
IHttpClientProxy<IAbpTenantAppService> proxy) |
|||
{ |
|||
Proxy = proxy; |
|||
} |
|||
|
|||
public async Task<TenantConfiguration> FindAsync(string name) |
|||
{ |
|||
//TODO: Cache
|
|||
|
|||
return CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name)); |
|||
} |
|||
|
|||
public async Task<TenantConfiguration> FindAsync(Guid id) |
|||
{ |
|||
//TODO: Cache
|
|||
|
|||
return CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id)); |
|||
} |
|||
|
|||
public TenantConfiguration Find(string name) |
|||
{ |
|||
//TODO: Cache
|
|||
|
|||
return AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name))); |
|||
} |
|||
|
|||
public TenantConfiguration Find(Guid id) |
|||
{ |
|||
//TODO: Cache
|
|||
|
|||
return AsyncHelper.RunSync(async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id))); |
|||
} |
|||
|
|||
protected virtual TenantConfiguration CreateTenantConfiguration(FindTenantResultDto tenantResultDto) |
|||
{ |
|||
if (!tenantResultDto.Success || tenantResultDto.TenantId == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return new TenantConfiguration(tenantResultDto.TenantId.Value, tenantResultDto.Name); |
|||
} |
|||
|
|||
protected virtual string CreateCacheKey(string tenantName) |
|||
{ |
|||
return $"RemoteTenantStore_Name_{tenantName}"; |
|||
} |
|||
|
|||
protected virtual string CreateCacheKey(Guid tenantId) |
|||
{ |
|||
return $"RemoteTenantStore_Id_{tenantId:N}"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,24 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<AssemblyName>Volo.Abp.AspNetCore.Mvc.Client.Common</AssemblyName> |
|||
<PackageId>Volo.Abp.AspNetCore.Mvc.Client.Common</PackageId> |
|||
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.Contracts\Volo.Abp.AspNetCore.Mvc.Contracts.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Caching\Volo.Abp.Caching.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Http.Client\Volo.Abp.Http.Client.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Localization\Volo.Abp.Localization.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,33 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.Http.Client; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Client |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpHttpClientModule), |
|||
typeof(AbpAspNetCoreMvcContractsModule), |
|||
typeof(AbpCachingModule), |
|||
typeof(AbpLocalizationModule) |
|||
)] |
|||
public class AbpAspNetCoreMvcClientCommonModule : AbpModule |
|||
{ |
|||
public const string RemoteServiceName = "AbpMvcClient"; |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddHttpClientProxies( |
|||
typeof(AbpAspNetCoreMvcContractsModule).Assembly, |
|||
RemoteServiceName, |
|||
asDefaultServices: false |
|||
); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.GlobalContributors.Add<RemoteLocalizationContributor>(); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,33 +1,11 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.Http.Client; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Client |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpHttpClientModule), |
|||
typeof(AbpAspNetCoreMvcContractsModule), |
|||
typeof(AbpCachingModule), |
|||
typeof(AbpLocalizationModule) |
|||
typeof(AbpAspNetCoreMvcClientCommonModule) |
|||
)] |
|||
public class AbpAspNetCoreMvcClientModule : AbpModule |
|||
{ |
|||
public const string RemoteServiceName = "AbpMvcClient"; |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddHttpClientProxies( |
|||
typeof(AbpAspNetCoreMvcContractsModule).Assembly, |
|||
RemoteServiceName, |
|||
asDefaultServices: false |
|||
); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.GlobalContributors.Add<RemoteLocalizationContributor>(); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,23 @@ |
|||
using System; |
|||
using Autofac; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp; |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly; |
|||
|
|||
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting |
|||
{ |
|||
public static class AbpWebAssemblyApplicationCreationOptionsAutofacExtensions |
|||
{ |
|||
public static void UseAutofac( |
|||
[NotNull] this AbpWebAssemblyApplicationCreationOptions options, |
|||
[CanBeNull] Action<ContainerBuilder> configure = null) |
|||
{ |
|||
options.HostBuilder.Services.AddAutofacServiceProviderFactory(); |
|||
options.HostBuilder.ConfigureContainer( |
|||
options.HostBuilder.Services.GetSingletonInstance<IServiceProviderFactory<ContainerBuilder>>(), |
|||
configure |
|||
); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.WebAssembly\Volo.Abp.AspNetCore.Components.WebAssembly.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,14 @@ |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.Autofac.WebAssembly |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAutofacModule), |
|||
typeof(AbpAspNetCoreComponentsWebAssemblyModule) |
|||
)] |
|||
public class AbpAutofacWebAssemblyModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,24 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.WebAssembly\Volo.Abp.AspNetCore.Components.WebAssembly.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Blazorise" Version="0.9.1.2" /> |
|||
<PackageReference Include="Blazorise.DataGrid" Version="0.9.1.2" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,23 @@ |
|||
using Blazorise; |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.BlazoriseUI |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAspNetCoreComponentsWebAssemblyModule) |
|||
)] |
|||
public class AbpBlazoriseUIModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
ConfigureBlazorise(context); |
|||
} |
|||
|
|||
private void ConfigureBlazorise(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services |
|||
.AddBlazorise(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,235 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Blazorise; |
|||
using Blazorise.DataGrid; |
|||
using Localization.Resources.AbpUi; |
|||
using Microsoft.AspNetCore.Components; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Localization; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly; |
|||
using Volo.Abp.ObjectMapping; |
|||
|
|||
namespace Volo.Abp.BlazoriseUI |
|||
{ |
|||
public abstract class BlazoriseCrudPageBase<TAppService, TEntityDto, TKey> |
|||
: BlazoriseCrudPageBase<TAppService, TEntityDto, TKey, PagedAndSortedResultRequestDto> |
|||
where TAppService : ICrudAppService<TEntityDto, TKey> |
|||
where TEntityDto : IEntityDto<TKey>, new() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public abstract class BlazoriseCrudPageBase<TAppService, TEntityDto, TKey, TGetListInput> |
|||
: BlazoriseCrudPageBase<TAppService, TEntityDto, TKey, TGetListInput, TEntityDto> |
|||
where TAppService : ICrudAppService<TEntityDto, TKey, TGetListInput> |
|||
where TEntityDto : IEntityDto<TKey>, new() |
|||
where TGetListInput : new() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public abstract class BlazoriseCrudPageBase<TAppService, TEntityDto, TKey, TGetListInput, TCreateInput> |
|||
: BlazoriseCrudPageBase<TAppService, TEntityDto, TKey, TGetListInput, TCreateInput, TCreateInput> |
|||
where TAppService : ICrudAppService<TEntityDto, TKey, TGetListInput, TCreateInput> |
|||
where TEntityDto : IEntityDto<TKey> |
|||
where TCreateInput : new() |
|||
where TGetListInput : new() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public abstract class BlazoriseCrudPageBase<TAppService, TEntityDto, TKey, TGetListInput, TCreateInput, TUpdateInput> |
|||
: BlazoriseCrudPageBase<TAppService, TEntityDto, TEntityDto, TKey, TGetListInput, TCreateInput, TUpdateInput> |
|||
where TAppService : ICrudAppService<TEntityDto, TKey, TGetListInput, TCreateInput, TUpdateInput> |
|||
where TEntityDto : IEntityDto<TKey> |
|||
where TCreateInput : new() |
|||
where TUpdateInput : new() |
|||
where TGetListInput : new() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public abstract class BlazoriseCrudPageBase<TAppService, TGetOutputDto, TGetListOutputDto, TKey, TGetListInput, TCreateInput, TUpdateInput> |
|||
: OwningComponentBase |
|||
where TAppService : ICrudAppService<TGetOutputDto, TGetListOutputDto, TKey, TGetListInput, TCreateInput, TUpdateInput> |
|||
where TGetOutputDto : IEntityDto<TKey> |
|||
where TGetListOutputDto : IEntityDto<TKey> |
|||
where TCreateInput : new() |
|||
where TUpdateInput : new() |
|||
where TGetListInput : new() |
|||
{ |
|||
[Inject] protected TAppService AppService { get; set; } |
|||
[Inject] protected IUiMessageService UiMessageService { get; set; } |
|||
[Inject] protected IStringLocalizer<AbpUiResource> UiLocalizer { get; set; } |
|||
|
|||
protected virtual int PageSize { get; } = LimitedResultRequestDto.DefaultMaxResultCount; |
|||
|
|||
protected int CurrentPage; |
|||
protected string CurrentSorting; |
|||
protected int? TotalCount; |
|||
protected IReadOnlyList<TGetListOutputDto> Entities = Array.Empty<TGetListOutputDto>(); |
|||
protected TCreateInput NewEntity; |
|||
protected TKey EditingEntityId; |
|||
protected TUpdateInput EditingEntity; |
|||
protected Modal CreateModal; |
|||
protected Modal EditModal; |
|||
|
|||
protected Type ObjectMapperContext { get; set; } |
|||
|
|||
protected IObjectMapper ObjectMapper |
|||
{ |
|||
get |
|||
{ |
|||
if (_objectMapper != null) |
|||
{ |
|||
return _objectMapper; |
|||
} |
|||
|
|||
if (ObjectMapperContext == null) |
|||
{ |
|||
return LazyGetRequiredService(ref _objectMapper); |
|||
} |
|||
|
|||
return LazyGetRequiredService( |
|||
typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext), |
|||
ref _objectMapper |
|||
); |
|||
} |
|||
} |
|||
|
|||
private IObjectMapper _objectMapper; |
|||
|
|||
protected TService LazyGetRequiredService<TService>(ref TService reference) |
|||
=> LazyGetRequiredService(typeof(TService), ref reference); |
|||
|
|||
protected TRef LazyGetRequiredService<TRef>(Type serviceType, ref TRef reference) |
|||
{ |
|||
if (reference == null) |
|||
{ |
|||
reference = (TRef) ScopedServices.GetRequiredService(serviceType); |
|||
} |
|||
|
|||
return reference; |
|||
} |
|||
|
|||
protected BlazoriseCrudPageBase() |
|||
{ |
|||
NewEntity = new TCreateInput(); |
|||
EditingEntity = new TUpdateInput(); |
|||
} |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
await GetEntitiesAsync(); |
|||
} |
|||
|
|||
protected virtual async Task GetEntitiesAsync() |
|||
{ |
|||
var input = await CreateGetListInputAsync(); |
|||
var result = await AppService.GetListAsync(input); |
|||
Entities = result.Items; |
|||
TotalCount = (int?) result.TotalCount; |
|||
} |
|||
|
|||
protected virtual Task<TGetListInput> CreateGetListInputAsync() |
|||
{ |
|||
var input = new TGetListInput(); |
|||
|
|||
if (input is ISortedResultRequest sortedResultRequestInput) |
|||
{ |
|||
sortedResultRequestInput.Sorting = CurrentSorting; |
|||
} |
|||
|
|||
if (input is IPagedResultRequest pagedResultRequestInput) |
|||
{ |
|||
pagedResultRequestInput.SkipCount = CurrentPage * PageSize; |
|||
} |
|||
|
|||
if (input is ILimitedResultRequest limitedResultRequestInput) |
|||
{ |
|||
limitedResultRequestInput.MaxResultCount = PageSize; |
|||
} |
|||
|
|||
return Task.FromResult(input); |
|||
} |
|||
|
|||
protected virtual async Task OnDataGridReadAsync(DataGridReadDataEventArgs<TGetListOutputDto> e) |
|||
{ |
|||
CurrentSorting = e.Columns |
|||
.Where(c => c.Direction != SortDirection.None) |
|||
.Select(c => c.Field + (c.Direction == SortDirection.Descending ? " DESC" : "")) |
|||
.JoinAsString(","); |
|||
CurrentPage = e.Page - 1; |
|||
|
|||
await GetEntitiesAsync(); |
|||
|
|||
StateHasChanged(); |
|||
} |
|||
|
|||
protected virtual Task OpenCreateModalAsync() |
|||
{ |
|||
NewEntity = new TCreateInput(); |
|||
CreateModal.Show(); |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual Task CloseCreateModalAsync() |
|||
{ |
|||
CreateModal.Hide(); |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual async Task OpenEditModalAsync(TKey id) |
|||
{ |
|||
var entityDto = await AppService.GetAsync(id); |
|||
EditingEntityId = id; |
|||
EditingEntity = MapToEditingEntity(entityDto); |
|||
EditModal.Show(); |
|||
} |
|||
|
|||
protected virtual TUpdateInput MapToEditingEntity(TGetOutputDto entityDto) |
|||
{ |
|||
return ObjectMapper.Map<TGetOutputDto, TUpdateInput>(entityDto); |
|||
} |
|||
|
|||
protected virtual Task CloseEditModalAsync() |
|||
{ |
|||
EditModal.Hide(); |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual async Task CreateEntityAsync() |
|||
{ |
|||
await AppService.CreateAsync(NewEntity); |
|||
await GetEntitiesAsync(); |
|||
CreateModal.Hide(); |
|||
} |
|||
|
|||
protected virtual async Task UpdateEntityAsync() |
|||
{ |
|||
await AppService.UpdateAsync(EditingEntityId, EditingEntity); |
|||
await GetEntitiesAsync(); |
|||
EditModal.Hide(); |
|||
} |
|||
|
|||
protected virtual async Task DeleteEntityAsync(TGetListOutputDto entity) |
|||
{ |
|||
if (!await UiMessageService.ConfirmAsync(GetDeleteConfirmationMessage(entity))) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await AppService.DeleteAsync(entity.Id); |
|||
await GetEntitiesAsync(); |
|||
} |
|||
|
|||
protected virtual string GetDeleteConfirmationMessage(TGetListOutputDto entity) |
|||
{ |
|||
return UiLocalizer["ItemWillBeDeletedMessage"]; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,25 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<AssemblyName>Volo.Abp.Http.Client.IdentityModel.WebAssembly</AssemblyName> |
|||
<PackageId>Volo.Abp.Http.Client.IdentityModel.WebAssembly</PackageId> |
|||
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="3.2.1" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.Http.Client.IdentityModel\Volo.Abp.Http.Client.IdentityModel.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,13 @@ |
|||
using System; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.Http.Client.IdentityModel.WebAssembly |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpHttpClientIdentityModelModule) |
|||
)] |
|||
public class AbpHttpClientIdentityModelWebAssemblyModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
using System.Threading.Tasks; |
|||
using IdentityModel.Client; |
|||
using Microsoft.AspNetCore.Components.WebAssembly.Authentication; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Http.Client.Authentication; |
|||
using Volo.Abp.IdentityModel; |
|||
|
|||
namespace Volo.Abp.Http.Client.IdentityModel.WebAssembly |
|||
{ |
|||
[Dependency(ReplaceServices = true)] |
|||
public class AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator : IdentityModelRemoteServiceHttpClientAuthenticator |
|||
{ |
|||
protected IAccessTokenProvider AccessTokenProvider { get; } |
|||
|
|||
public AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator( |
|||
IIdentityModelAuthenticationService identityModelAuthenticationService, |
|||
IAccessTokenProvider accessTokenProvider) |
|||
: base(identityModelAuthenticationService) |
|||
{ |
|||
AccessTokenProvider = accessTokenProvider; |
|||
} |
|||
|
|||
public override async Task Authenticate(RemoteServiceHttpClientAuthenticateContext context) |
|||
{ |
|||
if (context.RemoteService.GetUseCurrentAccessToken() != false) |
|||
{ |
|||
var accessToken = await GetAccessTokenFromAccessTokenProviderOrNullAsync(); |
|||
if (accessToken != null) |
|||
{ |
|||
context.Request.SetBearerToken(accessToken); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
await base.Authenticate(context); |
|||
} |
|||
|
|||
protected virtual async Task<string> GetAccessTokenFromAccessTokenProviderOrNullAsync() |
|||
{ |
|||
var result = await AccessTokenProvider.RequestAccessToken(); |
|||
if (result.Status != AccessTokenResultStatus.Success) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
result.TryGetToken(out var token); |
|||
return token.Value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Http.Client |
|||
{ |
|||
public class AbpHttpClientBuilderOptions |
|||
{ |
|||
public List<Action<string, IHttpClientBuilder>> ProxyClientBuildActions { get; } |
|||
|
|||
internal HashSet<string> ConfiguredProxyClients { get; } |
|||
|
|||
public AbpHttpClientBuilderOptions() |
|||
{ |
|||
ProxyClientBuildActions = new List<Action<string, IHttpClientBuilder>>(); |
|||
ConfiguredProxyClients = new HashSet<string>(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
using System; |
|||
using System.Security.Claims; |
|||
using System.Threading; |
|||
|
|||
namespace Volo.Abp.Security.Claims |
|||
{ |
|||
public abstract class CurrentPrincipalAccessorBase : ICurrentPrincipalAccessor |
|||
{ |
|||
public ClaimsPrincipal Principal => _currentPrincipal.Value ?? GetClaimsPrincipal(); |
|||
|
|||
private readonly AsyncLocal<ClaimsPrincipal> _currentPrincipal = new AsyncLocal<ClaimsPrincipal>(); |
|||
|
|||
protected abstract ClaimsPrincipal GetClaimsPrincipal(); |
|||
|
|||
public virtual IDisposable Change(ClaimsPrincipal principal) |
|||
{ |
|||
return SetCurrent(principal); |
|||
} |
|||
|
|||
private IDisposable SetCurrent(ClaimsPrincipal principal) |
|||
{ |
|||
var parent = Principal; |
|||
_currentPrincipal.Value = principal; |
|||
return new DisposeAction(() => |
|||
{ |
|||
_currentPrincipal.Value = parent; |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -1,34 +1,14 @@ |
|||
using System; |
|||
using System.Security.Claims; |
|||
using System.Security.Claims; |
|||
using System.Threading; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Security.Claims |
|||
{ |
|||
public class ThreadCurrentPrincipalAccessor : ICurrentPrincipalAccessor, ISingletonDependency |
|||
public class ThreadCurrentPrincipalAccessor : CurrentPrincipalAccessorBase, ISingletonDependency |
|||
{ |
|||
public ClaimsPrincipal Principal => _currentPrincipal.Value ?? GetClaimsPrincipal(); |
|||
|
|||
private readonly AsyncLocal<ClaimsPrincipal> _currentPrincipal = new AsyncLocal<ClaimsPrincipal>(); |
|||
|
|||
protected virtual ClaimsPrincipal GetClaimsPrincipal() |
|||
protected override ClaimsPrincipal GetClaimsPrincipal() |
|||
{ |
|||
return Thread.CurrentPrincipal as ClaimsPrincipal; |
|||
} |
|||
|
|||
public virtual IDisposable Change(ClaimsPrincipal principal) |
|||
{ |
|||
return SetCurrent(principal); |
|||
} |
|||
|
|||
private IDisposable SetCurrent(ClaimsPrincipal principal) |
|||
{ |
|||
var parent = Principal; |
|||
_currentPrincipal.Value = principal; |
|||
return new DisposeAction(() => |
|||
{ |
|||
_currentPrincipal.Value = parent; |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,13 @@ |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Ui.Branding |
|||
{ |
|||
public class DefaultBrandingProvider : IBrandingProvider, ITransientDependency |
|||
{ |
|||
public virtual string AppName => "MyApplication"; |
|||
|
|||
public virtual string LogoUrl => null; |
|||
|
|||
public virtual string LogoReverseUrl => null; |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
namespace Volo.Abp.Ui.Branding |
|||
{ |
|||
public interface IBrandingProvider |
|||
{ |
|||
string AppName { get; } |
|||
|
|||
/// <summary>
|
|||
/// Logo on white background
|
|||
/// </summary>
|
|||
string LogoUrl { get; } |
|||
|
|||
/// <summary>
|
|||
/// Logo on dark background
|
|||
/// </summary>
|
|||
string LogoReverseUrl { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming; |
|||
using Volo.Abp.AutoMapper; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.Blazor |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAspNetCoreComponentsWebAssemblyThemingModule), |
|||
typeof(AbpAutoMapperModule), |
|||
typeof(AbpFeatureManagementHttpApiClientModule) |
|||
)] |
|||
public class AbpFeatureManagementBlazorModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,85 @@ |
|||
@using Microsoft.Extensions.Localization |
|||
@using Volo.Abp.FeatureManagement.Localization |
|||
@using Volo.Abp.Validation.StringValues |
|||
@inject IStringLocalizer<AbpFeatureManagementResource> L |
|||
|
|||
<Modal @ref="_modal"> |
|||
<ModalBackdrop /> |
|||
<ModalContent Size="ModalSize.Large" IsCentered="true"> |
|||
<ModalHeader> |
|||
<ModalTitle>@L["Features"]</ModalTitle> |
|||
<CloseButton Clicked="CloseModal" /> |
|||
</ModalHeader> |
|||
<ModalBody MaxHeight="50"> |
|||
@if (_groups == null) |
|||
{ |
|||
<span>@L["NoFeatureFoundMessage"]</span> |
|||
} |
|||
else |
|||
{ |
|||
<Tabs TabPosition="TabPosition.Left" Pills="true" SelectedTab="@GetNormalizedGroupName(_groups.First().Name)"> |
|||
<Items> |
|||
@foreach (var group in _groups) |
|||
{ |
|||
<Tab Name="@GetNormalizedGroupName(group.Name)"> |
|||
<span>@group.DisplayName</span> |
|||
</Tab> |
|||
} |
|||
</Items> |
|||
<Content> |
|||
@foreach (var group in _groups) |
|||
{ |
|||
<TabPanel Name="@GetNormalizedGroupName(group.Name)"> |
|||
<h4>@group.DisplayName</h4> |
|||
|
|||
@foreach (var feature in group.Features) |
|||
{ |
|||
var disabled = IsDisabled(feature.Provider.Name); |
|||
|
|||
if (feature.ValueType is FreeTextStringValueType) |
|||
{ |
|||
<Field> |
|||
<FieldLabel>@feature.DisplayName</FieldLabel> |
|||
<TextEdit Disabled="@disabled" @bind-text="@feature.Value" /> |
|||
@if (feature.Description != null) |
|||
{ |
|||
<span>@feature.Description</span> |
|||
} |
|||
</Field> |
|||
} |
|||
|
|||
if (feature.ValueType is SelectionStringValueType) |
|||
{ |
|||
var items = ((SelectionStringValueType) feature.ValueType).ItemSource.Items; |
|||
|
|||
<Field> |
|||
<FieldLabel>@feature.DisplayName</FieldLabel> |
|||
<Select TValue="string" SelectedValue="feature.Value"> |
|||
@foreach (var item in items) |
|||
{ |
|||
<SelectItem Value="@item.Value">@item.DisplayText</SelectItem> |
|||
} |
|||
</Select> |
|||
</Field> |
|||
} |
|||
|
|||
if (feature.ValueType is ToggleStringValueType) |
|||
{ |
|||
<Field> |
|||
<Check TValue="bool" @bind-checked="@ToggleValues[feature.Name]">@feature.DisplayName</Check> |
|||
</Field> |
|||
} |
|||
} |
|||
|
|||
</TabPanel> |
|||
} |
|||
</Content> |
|||
</Tabs> |
|||
} |
|||
</ModalBody> |
|||
<ModalFooter> |
|||
<Button Color="Color.Secondary" Clicked="CloseModal">@L["Cancel"]</Button> |
|||
<Button Color="Color.Primary" Clicked="SaveAsync">@L["Save"]</Button> |
|||
</ModalFooter> |
|||
</ModalContent> |
|||
</Modal> |
|||
@ -0,0 +1,70 @@ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Blazorise; |
|||
using Microsoft.AspNetCore.Components; |
|||
using Volo.Abp.Features; |
|||
using Volo.Abp.Validation.StringValues; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.Blazor.Components |
|||
{ |
|||
public partial class FeatureManagementModal |
|||
{ |
|||
[Inject] private IFeatureAppService FeatureAppService { get; set; } |
|||
|
|||
private Modal _modal; |
|||
|
|||
private string _providerName; |
|||
private string _providerKey; |
|||
|
|||
private List<FeatureGroupDto> _groups { get; set; } |
|||
|
|||
private Dictionary<string, bool> ToggleValues; |
|||
|
|||
public async Task OpenAsync(string providerName, string providerKey) |
|||
{ |
|||
_providerName = providerName; |
|||
_providerKey = providerKey; |
|||
|
|||
_groups = (await FeatureAppService.GetAsync(_providerName, _providerKey)).Groups; |
|||
|
|||
ToggleValues = _groups |
|||
.SelectMany(x => x.Features) |
|||
.Where(x => x.ValueType is ToggleStringValueType) |
|||
.ToDictionary(x => x.Name, x => bool.Parse(x.Value)); |
|||
|
|||
_modal.Show(); |
|||
} |
|||
|
|||
private void CloseModal() |
|||
{ |
|||
_modal.Hide(); |
|||
} |
|||
|
|||
private async Task SaveAsync() |
|||
{ |
|||
var features = new UpdateFeaturesDto |
|||
{ |
|||
Features = _groups.SelectMany(g => g.Features).Select(f => new UpdateFeatureDto |
|||
{ |
|||
Name = f.Name, |
|||
Value = f.ValueType is ToggleStringValueType ? ToggleValues[f.Name].ToString() : f.Value |
|||
}).ToList() |
|||
}; |
|||
|
|||
await FeatureAppService.UpdateAsync(_providerName, _providerKey, features); |
|||
|
|||
_modal.Hide(); |
|||
} |
|||
|
|||
public string GetNormalizedGroupName(string name) |
|||
{ |
|||
return "FeatureGroup_" + name.Replace(".", "_"); |
|||
} |
|||
|
|||
public virtual bool IsDisabled(string providerName) |
|||
{ |
|||
return providerName != _providerName && providerName != DefaultValueFeatureValueProvider.ProviderName; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,29 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Razor"> |
|||
|
|||
<Import Project="..\..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.1</TargetFramework> |
|||
<RazorLangVersion>3.0</RazorLangVersion> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Components.WebAssembly.Theming\Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj" /> |
|||
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.FeatureManagement.HttpApi.Client\Volo.Abp.FeatureManagement.HttpApi.Client.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Content Update="_Imports.razor"> |
|||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile> |
|||
</Content> |
|||
<Content Update="Components\FeatureManagementModal.razor"> |
|||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile> |
|||
</Content> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,5 @@ |
|||
@using Microsoft.AspNetCore.Components.Web |
|||
@using Volo.Abp.AspNetCore.Components.WebAssembly |
|||
@using Volo.Abp.BlazoriseUI |
|||
@using Blazorise |
|||
@using Blazorise.DataGrid |
|||
@ -0,0 +1,4 @@ |
|||
src/Volo.Abp.Identity.HttpApi/Properties/launchSettings.json |
|||
src/Volo.Abp.Identity.Web/Properties/launchSettings.json |
|||
test/Volo.Abp.Identity.AspNetCore.Tests/Properties/launchSettings.json |
|||
src/Volo.Abp.Identity.AspNetCore/Properties/launchSettings.json |
|||
@ -0,0 +1,24 @@ |
|||
using AutoMapper; |
|||
using Volo.Abp.AutoMapper; |
|||
|
|||
namespace Volo.Abp.Identity.Blazor |
|||
{ |
|||
public class AbpIdentityBlazorAutoMapperProfile : Profile |
|||
{ |
|||
public AbpIdentityBlazorAutoMapperProfile() |
|||
{ |
|||
CreateMap<IdentityUserDto, IdentityUserUpdateDto>() |
|||
.MapExtraProperties() |
|||
.Ignore(x => x.Password) |
|||
.Ignore(x => x.RoleNames); |
|||
|
|||
CreateMap<IdentityRoleDto, IdentityRoleUpdateDto>() |
|||
.MapExtraProperties(); |
|||
|
|||
CreateMap<IdentityUserDto, IdentityUserUpdateDto>() |
|||
.Ignore(x => x.Password) |
|||
.Ignore(x => x.RoleNames) |
|||
.MapExtraProperties(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Routing; |
|||
using Volo.Abp.AutoMapper; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.PermissionManagement.Blazor; |
|||
using Volo.Abp.UI.Navigation; |
|||
|
|||
namespace Volo.Abp.Identity.Blazor |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpIdentityHttpApiClientModule), |
|||
typeof(AbpAutoMapperModule), |
|||
typeof(AbpPermissionManagementBlazorModule) |
|||
)] |
|||
public class AbpIdentityBlazorModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddAutoMapperObjectMapper<AbpIdentityBlazorModule>(); |
|||
|
|||
Configure<AbpAutoMapperOptions>(options => |
|||
{ |
|||
options.AddProfile<AbpIdentityBlazorAutoMapperProfile>(validate: true); |
|||
}); |
|||
|
|||
Configure<AbpNavigationOptions>(options => |
|||
{ |
|||
options.MenuContributors.Add(new AbpIdentityWebMainMenuContributor()); |
|||
}); |
|||
|
|||
Configure<AbpRouterOptions>(options => |
|||
{ |
|||
options.AdditionalAssemblies.Add(typeof(AbpIdentityBlazorModule).Assembly); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -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<IdentityResource>(); |
|||
|
|||
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")); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue