mirror of https://github.com/abpframework/abp.git
committed by
GitHub
65 changed files with 2133 additions and 253 deletions
@ -0,0 +1,92 @@ |
|||||
|
using System; |
||||
|
using System.Globalization; |
||||
|
using System.Linq.Dynamic.Core; |
||||
|
using System.Net.Http; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Microsoft.Extensions.Primitives; |
||||
|
using Volo.Abp.AspNetCore.Components.Web.Extensibility; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Http.Client; |
||||
|
using Volo.Abp.Http.Client.Authentication; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Server.Extensibility |
||||
|
{ |
||||
|
public class BlazorServerLookupApiRequestService : ILookupApiRequestService, ITransientDependency |
||||
|
{ |
||||
|
public IHttpClientFactory HttpClientFactory { get; } |
||||
|
public IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; } |
||||
|
|
||||
|
public AbpRemoteServiceOptions RemoteServiceOptions { get; } |
||||
|
|
||||
|
public ICurrentTenant CurrentTenant { get; } |
||||
|
public IHttpContextAccessor HttpContextAccessor { get; } |
||||
|
public NavigationManager NavigationManager { get; } |
||||
|
|
||||
|
public BlazorServerLookupApiRequestService(IHttpClientFactory httpClientFactory, |
||||
|
IRemoteServiceHttpClientAuthenticator httpClientAuthenticator, |
||||
|
ICurrentTenant currentTenant, |
||||
|
IOptions<AbpRemoteServiceOptions> remoteServiceOptions, |
||||
|
IHttpContextAccessor httpContextAccessor, |
||||
|
NavigationManager navigationManager) |
||||
|
{ |
||||
|
HttpClientFactory = httpClientFactory; |
||||
|
HttpClientAuthenticator = httpClientAuthenticator; |
||||
|
RemoteServiceOptions = remoteServiceOptions.Value; |
||||
|
CurrentTenant = currentTenant; |
||||
|
HttpContextAccessor = httpContextAccessor; |
||||
|
NavigationManager = navigationManager; |
||||
|
} |
||||
|
|
||||
|
public async Task<string> SendAsync(string url) |
||||
|
{ |
||||
|
var client = HttpClientFactory.CreateClient(); |
||||
|
var requestMessage = new HttpRequestMessage(HttpMethod.Get, url); |
||||
|
|
||||
|
var uri = new Uri(url, UriKind.RelativeOrAbsolute); |
||||
|
if (!uri.IsAbsoluteUri) |
||||
|
{ |
||||
|
var baseUrl = string.Empty; |
||||
|
try |
||||
|
{ |
||||
|
//Blazor tiered -- mode
|
||||
|
var remoteServiceConfig = RemoteServiceOptions.RemoteServices.GetConfigurationOrDefault("Default"); |
||||
|
baseUrl = remoteServiceConfig.BaseUrl; |
||||
|
client.BaseAddress = new Uri(baseUrl); |
||||
|
AddHeaders(requestMessage); |
||||
|
await HttpClientAuthenticator.Authenticate(new RemoteServiceHttpClientAuthenticateContext(client, |
||||
|
requestMessage, new RemoteServiceConfiguration(baseUrl), string.Empty)); |
||||
|
} |
||||
|
catch (AbpException) // Blazor-Server mode.
|
||||
|
{ |
||||
|
baseUrl = NavigationManager.BaseUri; |
||||
|
client.BaseAddress = new Uri(baseUrl); |
||||
|
foreach (var header in HttpContextAccessor.HttpContext.Request.Headers) |
||||
|
{ |
||||
|
requestMessage.Headers.Add(header.Key, header.Value.ToArray()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var response = await client.SendAsync(requestMessage); |
||||
|
return await response.Content.ReadAsStringAsync(); |
||||
|
} |
||||
|
|
||||
|
protected virtual void AddHeaders(HttpRequestMessage requestMessage) |
||||
|
{ |
||||
|
if (CurrentTenant.Id.HasValue) |
||||
|
{ |
||||
|
requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString()); |
||||
|
} |
||||
|
|
||||
|
var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name; |
||||
|
if (!currentCulture.IsNullOrEmpty()) |
||||
|
{ |
||||
|
requestMessage.Headers.AcceptLanguage.Add(new(currentCulture)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,78 @@ |
|||||
|
using System; |
||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars; |
||||
|
using Volo.Abp.BlazoriseUI; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Layout |
||||
|
{ |
||||
|
public partial class PageHeader : ComponentBase |
||||
|
{ |
||||
|
protected List<RenderFragment> ToolbarItemRenders { get; set; } |
||||
|
|
||||
|
public IPageToolbarManager PageToolbarManager { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public bool BreadcrumbShowHome { get; set; } = true; |
||||
|
|
||||
|
[Parameter] |
||||
|
public bool BreadcrumbShowCurrent { get; set; } = true; |
||||
|
|
||||
|
[Parameter] |
||||
|
public RenderFragment ChildContent { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public List<BreadcrumbItem> BreadcrumbItems { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public PageToolbar Toolbar { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public string PageName { get; set; } |
||||
|
|
||||
|
public PageHeader() |
||||
|
{ |
||||
|
BreadcrumbItems = new List<BreadcrumbItem>(); |
||||
|
ToolbarItemRenders = new List<RenderFragment>(); |
||||
|
} |
||||
|
|
||||
|
protected override async Task OnParametersSetAsync() |
||||
|
{ |
||||
|
await base.OnParametersSetAsync(); |
||||
|
if (Toolbar!=null) |
||||
|
{ |
||||
|
Console.WriteLine("Toolbar is not null"); |
||||
|
var toolbarItems = await PageToolbarManager.GetItemsAsync(Toolbar); |
||||
|
Console.WriteLine($"Toolbar item count:{toolbarItems.Length}"); |
||||
|
ToolbarItemRenders.Clear(); |
||||
|
|
||||
|
foreach (var item in toolbarItems) |
||||
|
{ |
||||
|
var sequence = 0; |
||||
|
ToolbarItemRenders.Add(builder => |
||||
|
{ |
||||
|
builder.OpenComponent(sequence, item.ComponentType); |
||||
|
if (item.Arguments != null) |
||||
|
{ |
||||
|
foreach (var argument in item.Arguments) |
||||
|
{ |
||||
|
sequence++; |
||||
|
builder.AddAttribute(sequence, argument.Key, argument.Value); |
||||
|
} |
||||
|
} |
||||
|
builder.CloseComponent(); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected override async Task OnInitializedAsync() |
||||
|
{ |
||||
|
await base.OnInitializedAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars |
||||
|
{ |
||||
|
public interface IPageToolbarContributor |
||||
|
{ |
||||
|
Task ContributeAsync(PageToolbarContributionContext context); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars |
||||
|
{ |
||||
|
public interface IPageToolbarManager |
||||
|
{ |
||||
|
Task<PageToolbarItem[]> GetItemsAsync(PageToolbar toolbar); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars |
||||
|
{ |
||||
|
public class PageToolbar |
||||
|
{ |
||||
|
public PageToolbarContributorList Contributors { get; set; } |
||||
|
|
||||
|
public PageToolbar() |
||||
|
{ |
||||
|
Contributors = new PageToolbarContributorList(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars |
||||
|
{ |
||||
|
public class PageToolbarContributionContext |
||||
|
{ |
||||
|
[NotNull] |
||||
|
public IServiceProvider ServiceProvider { get; } |
||||
|
|
||||
|
[NotNull] |
||||
|
public PageToolbarItemList Items { get; } |
||||
|
|
||||
|
public PageToolbarContributionContext( |
||||
|
[NotNull] IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
ServiceProvider = Check.NotNull(serviceProvider, nameof(serviceProvider)); |
||||
|
Items = new PageToolbarItemList(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars |
||||
|
{ |
||||
|
public abstract class PageToolbarContributor : IPageToolbarContributor |
||||
|
{ |
||||
|
public abstract Task ContributeAsync(PageToolbarContributionContext context); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars |
||||
|
{ |
||||
|
public class PageToolbarContributorList : List<IPageToolbarContributor> |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars |
||||
|
{ |
||||
|
public class PageToolbarDictionary : Dictionary<string, PageToolbar> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,71 @@ |
|||||
|
using Blazorise; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.BlazoriseUI.Components; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars |
||||
|
{ |
||||
|
public static class PageToolbarExtensions |
||||
|
{ |
||||
|
public static PageToolbar AddComponent<TComponent>( |
||||
|
this PageToolbar toolbar, |
||||
|
Dictionary<string, object> arguments = null, |
||||
|
int order = 0, |
||||
|
string requiredPolicyName = null) |
||||
|
{ |
||||
|
return toolbar.AddComponent( |
||||
|
typeof(TComponent), |
||||
|
arguments, |
||||
|
order, |
||||
|
requiredPolicyName |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public static PageToolbar AddComponent( |
||||
|
this PageToolbar toolbar, |
||||
|
Type componentType, |
||||
|
Dictionary<string, object> arguments = null, |
||||
|
int order = 0, |
||||
|
string requiredPolicyName = null) |
||||
|
{ |
||||
|
toolbar.Contributors.Add( |
||||
|
new SimplePageToolbarContributor( |
||||
|
componentType, |
||||
|
arguments, |
||||
|
order, |
||||
|
requiredPolicyName |
||||
|
) |
||||
|
); |
||||
|
|
||||
|
return toolbar; |
||||
|
} |
||||
|
|
||||
|
public static PageToolbar AddButton( |
||||
|
this PageToolbar toolbar, |
||||
|
string text, |
||||
|
Func<Task> clicked, |
||||
|
object icon = null, |
||||
|
Color color = Color.Primary, |
||||
|
bool disabled = false, |
||||
|
int order = 0, |
||||
|
string requiredPolicyName = null) |
||||
|
{ |
||||
|
toolbar.AddComponent<ToolbarButton>( |
||||
|
new Dictionary<string, object> |
||||
|
{ |
||||
|
{ nameof(ToolbarButton.Color), color}, |
||||
|
{ nameof(ToolbarButton.Text), text}, |
||||
|
{ nameof(ToolbarButton.Disabled), disabled}, |
||||
|
{ nameof(ToolbarButton.Icon), icon}, |
||||
|
{ nameof(ToolbarButton.Clicked),clicked}, |
||||
|
}, |
||||
|
order, |
||||
|
requiredPolicyName |
||||
|
); |
||||
|
|
||||
|
return toolbar; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars |
||||
|
{ |
||||
|
public class PageToolbarItem |
||||
|
{ |
||||
|
[NotNull] |
||||
|
public Type ComponentType { get; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
public Dictionary<string, object> Arguments { get; set; } |
||||
|
|
||||
|
public int Order { get; set; } |
||||
|
|
||||
|
public PageToolbarItem( |
||||
|
[NotNull] Type componentType, |
||||
|
[CanBeNull] Dictionary<string, object> arguments = null, |
||||
|
int order = 0) |
||||
|
{ |
||||
|
ComponentType = Check.NotNull(componentType, nameof(componentType)); |
||||
|
Arguments = arguments; |
||||
|
Order = order; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars |
||||
|
{ |
||||
|
public class PageToolbarItemList : List<PageToolbarItem> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars |
||||
|
{ |
||||
|
public class PageToolbarManager : IPageToolbarManager, ITransientDependency |
||||
|
{ |
||||
|
protected IHybridServiceScopeFactory ServiceScopeFactory { get; } |
||||
|
|
||||
|
public PageToolbarManager( |
||||
|
IHybridServiceScopeFactory serviceScopeFactory) |
||||
|
{ |
||||
|
ServiceScopeFactory = serviceScopeFactory; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<PageToolbarItem[]> GetItemsAsync(PageToolbar toolbar) |
||||
|
{ |
||||
|
if (toolbar == null || !toolbar.Contributors.Any()) |
||||
|
{ |
||||
|
return Array.Empty<PageToolbarItem>(); |
||||
|
} |
||||
|
|
||||
|
using (var scope = ServiceScopeFactory.CreateScope()) |
||||
|
{ |
||||
|
var context = new PageToolbarContributionContext(scope.ServiceProvider); |
||||
|
|
||||
|
foreach (var contributor in toolbar.Contributors) |
||||
|
{ |
||||
|
await contributor.ContributeAsync(context); |
||||
|
} |
||||
|
|
||||
|
return context.Items.OrderBy(i => i.Order).ToArray(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Theming.PageToolbars |
||||
|
{ |
||||
|
public class SimplePageToolbarContributor : IPageToolbarContributor |
||||
|
{ |
||||
|
public Type ComponentType { get; } |
||||
|
|
||||
|
public Dictionary<string, object> Arguments { get; set; } |
||||
|
|
||||
|
public int Order { get; } |
||||
|
|
||||
|
public string RequiredPolicyName { get; } |
||||
|
|
||||
|
public SimplePageToolbarContributor( |
||||
|
Type componentType, |
||||
|
Dictionary<string, object> arguments = null, |
||||
|
int order = 0, |
||||
|
string requiredPolicyName = null) |
||||
|
{ |
||||
|
ComponentType = componentType; |
||||
|
Arguments = arguments; |
||||
|
Order = order; |
||||
|
RequiredPolicyName = requiredPolicyName; |
||||
|
} |
||||
|
|
||||
|
public async Task ContributeAsync(PageToolbarContributionContext context) |
||||
|
{ |
||||
|
if (await ShouldAddComponentAsync(context)) |
||||
|
{ |
||||
|
context.Items.Add(new PageToolbarItem(ComponentType, Arguments, Order)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task<bool> ShouldAddComponentAsync(PageToolbarContributionContext context) |
||||
|
{ |
||||
|
if (RequiredPolicyName != null) |
||||
|
{ |
||||
|
var authorizationService = context.ServiceProvider.GetRequiredService<IAuthorizationService>(); |
||||
|
if (!await authorizationService.IsGrantedAsync(RequiredPolicyName)) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions |
||||
|
{ |
||||
|
public class EntityAction : IEquatable<EntityAction> |
||||
|
{ |
||||
|
public string Text { get; set; } |
||||
|
public Func<object, Task> Clicked { get; set; } |
||||
|
public Func<object, string> ConfirmationMessage { get; set; } |
||||
|
public bool Primary { get; set; } |
||||
|
public object Color { get; set; } |
||||
|
public string Icon { get; set; } |
||||
|
public Func<object, bool> Visible { get; set; } |
||||
|
public bool Equals(EntityAction other) |
||||
|
{ |
||||
|
return string.Equals(Text, other?.Text, StringComparison.OrdinalIgnoreCase); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions |
||||
|
{ |
||||
|
public class EntityActionDictionary : Dictionary<string, List<EntityAction>> |
||||
|
{ |
||||
|
public List<EntityAction> Get<T>() |
||||
|
{ |
||||
|
return this.GetOrAdd(typeof(T).FullName, () => new List<EntityAction>()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using JetBrains.Annotations; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Extensibility |
||||
|
{ |
||||
|
public interface ILookupApiRequestService |
||||
|
{ |
||||
|
Task<string> SendAsync([NotNull]string url); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns |
||||
|
{ |
||||
|
public class TableColumn |
||||
|
{ |
||||
|
public string Title { get; set; } |
||||
|
public string Data { get; set; } |
||||
|
[CanBeNull] |
||||
|
public string DisplayFormat { get; set; } |
||||
|
[CanBeNull] |
||||
|
public Type Component { get; set; } |
||||
|
public List<EntityAction> Actions { get; set; } |
||||
|
[CanBeNull] |
||||
|
public Func<object,string> ValueConverter { get; set; } |
||||
|
|
||||
|
public TableColumn() |
||||
|
{ |
||||
|
Actions = new List<EntityAction>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns |
||||
|
{ |
||||
|
public class TableColumnDictionary : Dictionary<string, List<TableColumn>> |
||||
|
{ |
||||
|
public List<TableColumn> Get<T>() |
||||
|
{ |
||||
|
return this.GetOrAdd(typeof(T).FullName, () => new List<TableColumn>()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,69 @@ |
|||||
|
using System; |
||||
|
using System.Globalization; |
||||
|
using System.Net.Http; |
||||
|
using System.Threading.Tasks; |
||||
|
using Castle.Components.DictionaryAdapter; |
||||
|
using Fody; |
||||
|
using Volo.Abp.AspNetCore.Components.Web.Extensibility; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Http.Client.Authentication; |
||||
|
using Volo.Abp.Http.Client; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Extensibility |
||||
|
{ |
||||
|
public class WebAssemblyLookupApiRequestService : ILookupApiRequestService, ITransientDependency |
||||
|
{ |
||||
|
public IHttpClientFactory HttpClientFactory { get; } |
||||
|
public IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; } |
||||
|
|
||||
|
public AbpRemoteServiceOptions RemoteServiceOptions { get; } |
||||
|
|
||||
|
public ICurrentTenant CurrentTenant { get; } |
||||
|
|
||||
|
public WebAssemblyLookupApiRequestService(IHttpClientFactory httpClientFactory, |
||||
|
IRemoteServiceHttpClientAuthenticator httpClientAuthenticator, |
||||
|
ICurrentTenant currentTenant, |
||||
|
IOptions<AbpRemoteServiceOptions> remoteServiceOptions) |
||||
|
{ |
||||
|
HttpClientFactory = httpClientFactory; |
||||
|
HttpClientAuthenticator = httpClientAuthenticator; |
||||
|
RemoteServiceOptions = remoteServiceOptions.Value; |
||||
|
CurrentTenant = currentTenant; |
||||
|
} |
||||
|
|
||||
|
public async Task<string> SendAsync(string url) |
||||
|
{ |
||||
|
var client = HttpClientFactory.CreateClient(); |
||||
|
var requestMessage = new HttpRequestMessage(HttpMethod.Get, url); |
||||
|
AddHeaders(requestMessage); |
||||
|
|
||||
|
var uri = new Uri(url, UriKind.RelativeOrAbsolute); |
||||
|
if (!uri.IsAbsoluteUri) |
||||
|
{ |
||||
|
var remoteServiceConfig = RemoteServiceOptions.RemoteServices.GetConfigurationOrDefault("Default"); |
||||
|
client.BaseAddress = new Uri(remoteServiceConfig.BaseUrl); |
||||
|
await HttpClientAuthenticator.Authenticate(new RemoteServiceHttpClientAuthenticateContext(client, requestMessage, new RemoteServiceConfiguration(remoteServiceConfig.BaseUrl), string.Empty)); |
||||
|
} |
||||
|
|
||||
|
var response = await client.SendAsync(requestMessage); |
||||
|
|
||||
|
return await response.Content.ReadAsStringAsync(); |
||||
|
} |
||||
|
|
||||
|
protected virtual void AddHeaders(HttpRequestMessage requestMessage) |
||||
|
{ |
||||
|
if (CurrentTenant.Id.HasValue) |
||||
|
{ |
||||
|
requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString()); |
||||
|
} |
||||
|
|
||||
|
var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name; |
||||
|
if (!currentCulture.IsNullOrEmpty()) |
||||
|
{ |
||||
|
requestMessage.Headers.AcceptLanguage.Add(new (currentCulture)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,261 @@ |
|||||
|
using Blazorise; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.BlazoriseUI.Components.ObjectExtending; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
using Volo.Abp.Reflection; |
||||
|
|
||||
|
namespace Volo.Abp.BlazoriseUI |
||||
|
{ |
||||
|
public static class BlazoriseUiObjectExtensionPropertyInfoExtensions |
||||
|
{ |
||||
|
private static readonly HashSet<Type> NumberTypes = new HashSet<Type> { |
||||
|
typeof(int), |
||||
|
typeof(long), |
||||
|
typeof(byte), |
||||
|
typeof(sbyte), |
||||
|
typeof(short), |
||||
|
typeof(ushort), |
||||
|
typeof(uint), |
||||
|
typeof(long), |
||||
|
typeof(ulong), |
||||
|
typeof(float), |
||||
|
typeof(double), |
||||
|
typeof(decimal), |
||||
|
typeof(int?), |
||||
|
typeof(long?), |
||||
|
typeof(byte?), |
||||
|
typeof(sbyte?), |
||||
|
typeof(short?), |
||||
|
typeof(ushort?), |
||||
|
typeof(uint?), |
||||
|
typeof(long?), |
||||
|
typeof(ulong?), |
||||
|
typeof(float?), |
||||
|
typeof(double?), |
||||
|
typeof(decimal?) |
||||
|
}; |
||||
|
|
||||
|
private static readonly HashSet<Type> TextEditSupportedAttributeTypes = new HashSet<Type> { |
||||
|
typeof(EmailAddressAttribute), |
||||
|
typeof(UrlAttribute), |
||||
|
typeof(PhoneAttribute) |
||||
|
}; |
||||
|
|
||||
|
public static string GetDateEditInputFormatOrNull(this IBasicObjectExtensionPropertyInfo property) |
||||
|
{ |
||||
|
if (property.IsDate()) |
||||
|
{ |
||||
|
return "{0:yyyy-MM-dd}"; |
||||
|
} |
||||
|
|
||||
|
if (property.IsDateTime()) |
||||
|
{ |
||||
|
return "{0:yyyy-MM-ddTHH:mm}"; |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public static string GetTextInputValueOrNull(this IBasicObjectExtensionPropertyInfo property, object value) |
||||
|
{ |
||||
|
if (value == null) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
if (TypeHelper.IsFloatingType(property.Type)) |
||||
|
{ |
||||
|
return value.ToString()?.Replace(',', '.'); |
||||
|
} |
||||
|
|
||||
|
return value.ToString(); |
||||
|
} |
||||
|
|
||||
|
public static T GetInputValueOrDefault<T>(this IBasicObjectExtensionPropertyInfo property, object value) |
||||
|
{ |
||||
|
if (value == null) |
||||
|
{ |
||||
|
return default; |
||||
|
} |
||||
|
|
||||
|
return (T)value; |
||||
|
} |
||||
|
|
||||
|
public static TextInputMode GetTextInputMode(this ObjectExtensionPropertyInfo propertyInfo) |
||||
|
{ |
||||
|
foreach (var attribute in propertyInfo.Attributes) |
||||
|
{ |
||||
|
var textRoleByAttribute = GetTextInputModeFromAttributeOrNull(attribute); |
||||
|
if (textRoleByAttribute != null) |
||||
|
{ |
||||
|
return textRoleByAttribute.Value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return GetTextInputModeFromTypeOrNull(propertyInfo.Type) |
||||
|
?? TextInputMode.None; //default
|
||||
|
} |
||||
|
|
||||
|
private static TextInputMode? GetTextInputModeFromTypeOrNull(Type type) |
||||
|
{ |
||||
|
if (TypeHelper.IsFloatingType(type)) |
||||
|
{ |
||||
|
return TextInputMode.Decimal; |
||||
|
} |
||||
|
|
||||
|
if (NumberTypes.Contains(type)) |
||||
|
{ |
||||
|
return TextInputMode.Numeric; |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
private static TextInputMode? GetTextInputModeFromAttributeOrNull(Attribute attribute) |
||||
|
{ |
||||
|
if (attribute is EmailAddressAttribute) |
||||
|
{ |
||||
|
return TextInputMode.Email; |
||||
|
} |
||||
|
|
||||
|
if (attribute is UrlAttribute) |
||||
|
{ |
||||
|
return TextInputMode.Url; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
if (attribute is PhoneAttribute) |
||||
|
{ |
||||
|
return TextInputMode.Tel; |
||||
|
} |
||||
|
|
||||
|
if (attribute is DataTypeAttribute dataTypeAttribute) |
||||
|
{ |
||||
|
switch (dataTypeAttribute.DataType) |
||||
|
{ |
||||
|
case DataType.EmailAddress: |
||||
|
return TextInputMode.Email; |
||||
|
case DataType.Url: |
||||
|
return TextInputMode.Url; |
||||
|
case DataType.PhoneNumber: |
||||
|
return TextInputMode.Tel; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public static TextRole GetTextRole(this ObjectExtensionPropertyInfo propertyInfo) |
||||
|
{ |
||||
|
foreach (var attribute in propertyInfo.Attributes) |
||||
|
{ |
||||
|
var textRoleByAttribute = GetTextRoleFromAttributeOrNull(attribute); |
||||
|
if (textRoleByAttribute != null) |
||||
|
{ |
||||
|
return textRoleByAttribute.Value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return TextRole.Text; //default
|
||||
|
} |
||||
|
|
||||
|
private static TextRole? GetTextRoleFromAttributeOrNull(Attribute attribute) |
||||
|
{ |
||||
|
if (attribute is EmailAddressAttribute) |
||||
|
{ |
||||
|
return TextRole.Email; |
||||
|
} |
||||
|
|
||||
|
if (attribute is UrlAttribute) |
||||
|
{ |
||||
|
return TextRole.Url; |
||||
|
} |
||||
|
|
||||
|
if (attribute is DataTypeAttribute dataTypeAttribute) |
||||
|
{ |
||||
|
switch (dataTypeAttribute.DataType) |
||||
|
{ |
||||
|
case DataType.Password: |
||||
|
return TextRole.Password; |
||||
|
case DataType.EmailAddress: |
||||
|
return TextRole.Email; |
||||
|
case DataType.Url: |
||||
|
return TextRole.Url; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public static Type GetInputType(this ObjectExtensionPropertyInfo propertyInfo) |
||||
|
{ |
||||
|
foreach (var attribute in propertyInfo.Attributes) |
||||
|
{ |
||||
|
var inputTypeByAttribute = GetInputTypeFromAttributeOrNull(attribute); |
||||
|
if (inputTypeByAttribute != null) |
||||
|
{ |
||||
|
return inputTypeByAttribute; |
||||
|
} |
||||
|
} |
||||
|
return GetInputTypeFromTypeOrNull(propertyInfo.Type) |
||||
|
?? typeof(TextExtensionProperty<,>); //default
|
||||
|
} |
||||
|
|
||||
|
private static Type GetInputTypeFromAttributeOrNull(Attribute attribute) |
||||
|
{ |
||||
|
var hasTextEditSupport = TextEditSupportedAttributeTypes.Any(t => t == attribute.GetType()); |
||||
|
|
||||
|
if (hasTextEditSupport) |
||||
|
{ |
||||
|
return typeof(TextExtensionProperty<,>); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
if (attribute is DataTypeAttribute dataTypeAttribute) |
||||
|
{ |
||||
|
switch (dataTypeAttribute.DataType) |
||||
|
{ |
||||
|
case DataType.Password: |
||||
|
return typeof(TextExtensionProperty<,>); |
||||
|
case DataType.Date: |
||||
|
return typeof(DateTimeExtensionProperty<,>); |
||||
|
case DataType.Time: |
||||
|
return typeof(TimeExtensionProperty<,>); |
||||
|
case DataType.EmailAddress: |
||||
|
return typeof(TextExtensionProperty<,>); |
||||
|
case DataType.Url: |
||||
|
return typeof(TextExtensionProperty<,>); |
||||
|
case DataType.PhoneNumber: |
||||
|
return typeof(TextExtensionProperty<,>); |
||||
|
case DataType.DateTime: |
||||
|
return typeof(DateTimeExtensionProperty<,>); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
private static Type GetInputTypeFromTypeOrNull(Type type) |
||||
|
{ |
||||
|
if (type == typeof(bool)) |
||||
|
{ |
||||
|
return typeof(CheckExtensionProperty<,>); |
||||
|
} |
||||
|
|
||||
|
if (type == typeof(DateTime)) |
||||
|
{ |
||||
|
return typeof(DateTimeExtensionProperty<,>); |
||||
|
} |
||||
|
|
||||
|
if (NumberTypes.Contains(type)) |
||||
|
{ |
||||
|
return typeof(TextExtensionProperty<,>); |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,121 @@ |
|||||
|
@typeparam TItem |
||||
|
@using Blazorise.DataGrid; |
||||
|
@using Volo.Abp.Data |
||||
|
@using Volo.Abp.BlazoriseUI.Components.ObjectExtending |
||||
|
|
||||
|
<DataGrid TItem="TItem" |
||||
|
Data="@Data" |
||||
|
ReadData="@ReadData" |
||||
|
TotalItems="@TotalItems" |
||||
|
ShowPager="@ShowPager" |
||||
|
CurrentPage="@CurrentPage" |
||||
|
PageSize="@PageSize"> |
||||
|
<DataGridColumns> |
||||
|
@if (Columns != null) |
||||
|
{ |
||||
|
@foreach (var column in Columns) |
||||
|
{ |
||||
|
if (column.Actions.Any()) |
||||
|
{ |
||||
|
<DataGridEntityActionsColumn TItem="TItem" @ref="ActionColumns[column.Title]" Caption="@column.Title"> |
||||
|
<DisplayTemplate> |
||||
|
<EntityActions TItem="TItem" EntityActionsColumn="ActionColumns[column.Title]"> |
||||
|
@foreach (var action in column.Actions) |
||||
|
{ |
||||
|
if (action.ConfirmationMessage != null) |
||||
|
{ |
||||
|
<EntityAction TItem="TItem" |
||||
|
Color="@(action.Color!=null ? (Blazorise.Color)action.Color : Blazorise.Color.Primary)" |
||||
|
Icon="@action.Icon" |
||||
|
Clicked="async () => await action.Clicked(context)" |
||||
|
ConfirmationMessage="() => action.ConfirmationMessage.Invoke(context)" |
||||
|
Visible="@(action.Visible!=null ? action.Visible(context) : true)" |
||||
|
Text="@action.Text"> |
||||
|
</EntityAction> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<EntityAction TItem="TItem" |
||||
|
Clicked="async () => await action.Clicked(context)" |
||||
|
Color="@(action.Color!=null ? (Blazorise.Color)action.Color : Blazorise.Color.None)" |
||||
|
Icon="@action.Icon" |
||||
|
Visible="@(action.Visible!=null ? action.Visible(context) : true)" |
||||
|
Text="@action.Text"> |
||||
|
</EntityAction> |
||||
|
} |
||||
|
} |
||||
|
</EntityActions> |
||||
|
</DisplayTemplate> |
||||
|
</DataGridEntityActionsColumn> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
@if (column.Component != null) |
||||
|
{ |
||||
|
<DataGridColumn TItem="TItem" Field="@typeof(TItem).GetProperties().First().Name" Caption="@column.Title"> |
||||
|
<DisplayTemplate> |
||||
|
@RenderCustomTableColumnComponent(column.Component, context) |
||||
|
</DisplayTemplate> |
||||
|
</DataGridColumn> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (!ExtensionPropertiesRegex.IsMatch(column.Data)) |
||||
|
{ |
||||
|
<DataGridColumn TItem="TItem" Field="@column.Data" Caption="@column.Title"/> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<DataGridColumn TItem="TItem" Field="@nameof(IHasExtraProperties.ExtraProperties)" Caption="@column.Title"> |
||||
|
<DisplayTemplate> |
||||
|
@{ |
||||
|
var entity = context as IHasExtraProperties; |
||||
|
var propertyName = ExtensionPropertiesRegex.Match(column.Data).Groups[1].Value; |
||||
|
var propertyValue = entity.GetProperty(propertyName); |
||||
|
if (propertyValue != null && propertyValue.GetType() == typeof(bool)) |
||||
|
{ |
||||
|
if ((bool) propertyValue) |
||||
|
{ |
||||
|
<Icon class="text-success" Name="IconName.Check"/> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<Icon class="text-danger" Name="IconName.Times"/> |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (column.ValueConverter != null) |
||||
|
{ |
||||
|
if (column.DisplayFormat == null) |
||||
|
{ |
||||
|
@(column.ValueConverter(propertyValue)) |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
@(string.Format(column.DisplayFormat, column.ValueConverter(propertyValue))) |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (column.DisplayFormat == null) |
||||
|
{ |
||||
|
@(propertyValue) |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
@(string.Format(column.DisplayFormat, propertyValue)) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</DisplayTemplate> |
||||
|
</DataGridColumn> |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</DataGridColumns> |
||||
|
</DataGrid> |
||||
@ -0,0 +1,50 @@ |
|||||
|
using System; |
||||
|
using Blazorise.Extensions; |
||||
|
using Blazorise.DataGrid; |
||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text.RegularExpressions; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions; |
||||
|
using Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns; |
||||
|
|
||||
|
namespace Volo.Abp.BlazoriseUI.Components |
||||
|
{ |
||||
|
public partial class AbpExtensibleDataGrid<TItem> : ComponentBase |
||||
|
{ |
||||
|
protected const string DataFieldAttributeName = "Data"; |
||||
|
|
||||
|
protected Dictionary<string, DataGridEntityActionsColumn<TItem>> ActionColumns = |
||||
|
new Dictionary<string, DataGridEntityActionsColumn<TItem>>(); |
||||
|
|
||||
|
protected Regex ExtensionPropertiesRegex = new Regex(@"ExtraProperties\[(.*?)\]"); |
||||
|
|
||||
|
[Parameter] public IEnumerable<TItem> Data { get; set; } |
||||
|
|
||||
|
[Parameter] public EventCallback<DataGridReadDataEventArgs<TItem>> ReadData { get; set; } |
||||
|
|
||||
|
[Parameter] public int? TotalItems { get; set; } |
||||
|
|
||||
|
[Parameter] public bool ShowPager { get; set; } |
||||
|
|
||||
|
[Parameter] public int PageSize { get; set; } |
||||
|
|
||||
|
[Parameter] public IEnumerable<TableColumn> Columns { get; set; } |
||||
|
|
||||
|
[Parameter] public int CurrentPage { get; set; } = 1; |
||||
|
|
||||
|
[Inject] |
||||
|
public IStringLocalizerFactory StringLocalizerFactory { get; set; } |
||||
|
|
||||
|
protected virtual RenderFragment RenderCustomTableColumnComponent(Type type, object data) |
||||
|
{ |
||||
|
return (builder) => |
||||
|
{ |
||||
|
builder.OpenComponent(type); |
||||
|
builder.AddAttribute(0, DataFieldAttributeName, data); |
||||
|
builder.CloseComponent(); |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
@typeparam TEntity |
||||
|
@typeparam TResourceType |
||||
|
@using Volo.Abp.BlazoriseUI |
||||
|
@using Volo.Abp.Localization |
||||
|
|
||||
|
@if (PropertyInfo != null && Entity != null) |
||||
|
{ |
||||
|
<Field> |
||||
|
<Check TValue="bool" @bind-Checked="@Value">@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)</Check> |
||||
|
</Field> |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
|
||||
|
namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending |
||||
|
{ |
||||
|
public partial class CheckExtensionProperty<TEntity, TResourceType> : ComponentBase |
||||
|
where TEntity : IHasExtraProperties |
||||
|
{ |
||||
|
[Inject] |
||||
|
public IStringLocalizerFactory StringLocalizerFactory { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public TEntity Entity { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public ObjectExtensionPropertyInfo PropertyInfo { get; set; } |
||||
|
|
||||
|
protected bool Value |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return PropertyInfo.GetInputValueOrDefault<bool>(Entity.GetProperty(PropertyInfo.Name)); |
||||
|
} |
||||
|
set |
||||
|
{ |
||||
|
Entity.SetProperty(PropertyInfo.Name, value, false); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
@typeparam TEntity |
||||
|
@typeparam TResourceType |
||||
|
@using Volo.Abp.BlazoriseUI |
||||
|
@using Volo.Abp.Localization |
||||
|
@using Volo.Abp.ObjectExtending |
||||
|
|
||||
|
@if (PropertyInfo != null && Entity != null) |
||||
|
{ |
||||
|
<Field> |
||||
|
<FieldLabel>@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)</FieldLabel> |
||||
|
<DateEdit TValue="DateTime?" |
||||
|
InputMode="@(PropertyInfo.IsDate() ? DateInputMode.Date : DateInputMode.DateTime)" |
||||
|
Pattern="@PropertyInfo.GetDateEditInputFormatOrNull()" |
||||
|
@bind-Date="@Value"> |
||||
|
</DateEdit> |
||||
|
</Field> |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
|
||||
|
namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending |
||||
|
{ |
||||
|
public partial class DateTimeExtensionProperty<TEntity, TResourceType> : ComponentBase |
||||
|
where TEntity : IHasExtraProperties |
||||
|
{ |
||||
|
[Inject] |
||||
|
public IStringLocalizerFactory StringLocalizerFactory { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public TEntity Entity { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public ObjectExtensionPropertyInfo PropertyInfo { get; set; } |
||||
|
|
||||
|
protected DateTime? Value |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return PropertyInfo.GetInputValueOrDefault<DateTime?>(Entity.GetProperty(PropertyInfo.Name)); |
||||
|
} |
||||
|
set |
||||
|
{ |
||||
|
Entity.SetProperty(PropertyInfo.Name, value, false); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
using Microsoft.Extensions.Localization; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending |
||||
|
{ |
||||
|
public static class EnumHelper |
||||
|
{ |
||||
|
public static string GetLocalizedMemberName(Type enumType, object value, IStringLocalizerFactory stringLocalizerFactory) |
||||
|
{ |
||||
|
var memberName = enumType.GetEnumName(value); |
||||
|
var localizedMemberName = AbpInternalLocalizationHelper.LocalizeWithFallback( |
||||
|
new[] |
||||
|
{ |
||||
|
stringLocalizerFactory.CreateDefaultOrNull() |
||||
|
}, |
||||
|
new[] |
||||
|
{ |
||||
|
$"Enum:{enumType.Name}.{memberName}", |
||||
|
$"{enumType.Name}.{memberName}", |
||||
|
memberName |
||||
|
}, |
||||
|
memberName |
||||
|
); |
||||
|
|
||||
|
return localizedMemberName; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
@typeparam TEntityType |
||||
|
@typeparam TResourceType |
||||
|
@using Volo.Abp.ObjectExtending |
||||
|
@using Volo.Abp.Localization |
||||
|
@using Volo.Abp.Data |
||||
|
|
||||
|
@foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties<TEntityType>()) |
||||
|
{ |
||||
|
if (!propertyInfo.Name.EndsWith("_Text")) |
||||
|
{ |
||||
|
if (propertyInfo.Type.IsEnum) |
||||
|
{ |
||||
|
<SelectExtensionProperty PropertyInfo="@propertyInfo" Entity="@Entity" TEntity="TEntityType" TResourceType="TResourceType" /> |
||||
|
} |
||||
|
else if (!propertyInfo.Lookup.Url.IsNullOrEmpty()) |
||||
|
{ |
||||
|
<LookupExtensionProperty PropertyInfo="@propertyInfo" Entity="@Entity" TEntity="TEntityType" TResourceType="TResourceType" /> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
var inputType = propertyInfo.GetInputType(); |
||||
|
|
||||
|
__builder.OpenComponent(0, inputType.MakeGenericType(new[] { typeof(TEntityType), typeof(TResourceType) })); |
||||
|
__builder.AddAttribute(1, "PropertyInfo", propertyInfo); |
||||
|
__builder.AddAttribute(2, "Entity", Entity); |
||||
|
__builder.CloseComponent(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
using Volo.Abp.AspNetCore.Components.Web; |
||||
|
using Volo.Abp.Data; |
||||
|
|
||||
|
namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending |
||||
|
{ |
||||
|
public partial class ExtensionProperties<TEntityType, TResourceType> : ComponentBase |
||||
|
where TEntityType : IHasExtraProperties |
||||
|
{ |
||||
|
[Inject] |
||||
|
public IStringLocalizerFactory StringLocalizerFactory { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public AbpBlazorMessageLocalizerHelper<TResourceType> LH { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public TEntityType Entity { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
@typeparam TEntity |
||||
|
@typeparam TResourceType |
||||
|
@using Abp.Localization |
||||
|
@using Blazorise.Components |
||||
|
|
||||
|
<Field> |
||||
|
<FieldLabel>@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)</FieldLabel> |
||||
|
<Autocomplete Data="@lookupItems" |
||||
|
TItem="SelectItem<object>" |
||||
|
TValue="object" |
||||
|
TextField="item=>item.Text" |
||||
|
ValueField="item=>item.Value" |
||||
|
SelectedValue="@SelectedValue" |
||||
|
SelectedValueChanged="@SelectedValueChanged" |
||||
|
SearchChanged="@SearchFilterChangedAsync"> |
||||
|
</Autocomplete> |
||||
|
</Field> |
||||
|
|
||||
@ -0,0 +1,109 @@ |
|||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Globalization; |
||||
|
using System.Linq; |
||||
|
using System.Net.Http; |
||||
|
using System.Net.Http.Headers; |
||||
|
using System.Text.Json; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.Components.Web.Extensibility; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.Http; |
||||
|
using Volo.Abp.Http.Client; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
|
||||
|
namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending |
||||
|
{ |
||||
|
public partial class LookupExtensionProperty<TEntity, TResourceType> : ComponentBase |
||||
|
where TEntity : IHasExtraProperties |
||||
|
{ |
||||
|
protected List<SelectItem<object>> lookupItems; |
||||
|
|
||||
|
[Inject] public IStringLocalizerFactory StringLocalizerFactory { get; set; } |
||||
|
|
||||
|
[Parameter] public TEntity Entity { get; set; } |
||||
|
|
||||
|
[Parameter] public ObjectExtensionPropertyInfo PropertyInfo { get; set; } |
||||
|
|
||||
|
|
||||
|
[Inject] public ILookupApiRequestService LookupApiService { get; set; } |
||||
|
|
||||
|
public string TextPropertyName => PropertyInfo.Name + "_Text"; |
||||
|
|
||||
|
public object SelectedValue |
||||
|
{ |
||||
|
get { return Entity.GetProperty(PropertyInfo.Name); } |
||||
|
set |
||||
|
{ |
||||
|
Entity.SetProperty(PropertyInfo.Name, value, false); |
||||
|
UpdateLookupTextProperty(value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public LookupExtensionProperty() |
||||
|
{ |
||||
|
lookupItems = new List<SelectItem<object>>(); |
||||
|
} |
||||
|
|
||||
|
protected override void OnParametersSet() |
||||
|
{ |
||||
|
var value = Entity.GetProperty(PropertyInfo.Name); |
||||
|
var text = Entity.GetProperty(TextPropertyName); |
||||
|
if (value != null && text != null) |
||||
|
{ |
||||
|
lookupItems.Add(new SelectItem<object> |
||||
|
{ |
||||
|
Text = Entity.GetProperty(TextPropertyName).ToString(), |
||||
|
Value = value |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual void UpdateLookupTextProperty(object value) |
||||
|
{ |
||||
|
var selectedItemText = lookupItems.SingleOrDefault(t => t.Value.Equals(value)).Text; |
||||
|
Entity.SetProperty(TextPropertyName, selectedItemText); |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task<List<SelectItem<object>>> GetLookupItemsAsync(string filter) |
||||
|
{ |
||||
|
var selectItems = new List<SelectItem<object>>(); |
||||
|
|
||||
|
var url = PropertyInfo.Lookup.Url; |
||||
|
if (!filter.IsNullOrEmpty()) |
||||
|
{ |
||||
|
url += $"?{PropertyInfo.Lookup.FilterParamName}={filter.Trim()}"; |
||||
|
} |
||||
|
|
||||
|
var response = await LookupApiService.SendAsync(url); |
||||
|
|
||||
|
var document = JsonDocument.Parse(response); |
||||
|
var itemsArrayProp = document.RootElement.GetProperty(PropertyInfo.Lookup.ResultListPropertyName); |
||||
|
foreach (var item in itemsArrayProp.EnumerateArray()) |
||||
|
{ |
||||
|
selectItems.Add(new SelectItem<object> |
||||
|
{ |
||||
|
Text = item.GetProperty(PropertyInfo.Lookup.DisplayPropertyName).GetString(), |
||||
|
Value = JsonSerializer.Deserialize( |
||||
|
item.GetProperty(PropertyInfo.Lookup.ValuePropertyName).GetRawText(), PropertyInfo.Type) |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
return selectItems; |
||||
|
} |
||||
|
|
||||
|
protected virtual void SelectedValueChanged(object selectedItem) |
||||
|
{ |
||||
|
SelectedValue = selectedItem; |
||||
|
} |
||||
|
|
||||
|
protected async Task SearchFilterChangedAsync(string filter) |
||||
|
{ |
||||
|
lookupItems = await GetLookupItemsAsync(filter); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
@typeparam TEntity |
||||
|
@typeparam TResourceType |
||||
|
@using Abp.Localization |
||||
|
|
||||
|
<Field> |
||||
|
<FieldLabel>@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)</FieldLabel> |
||||
|
<Select @bind-SelectedValue="@SelectedValue" > |
||||
|
@foreach (var item in SelectItems) |
||||
|
{ |
||||
|
<SelectItem Value="@item.Value">@item.Text</SelectItem> |
||||
|
} |
||||
|
</Select> |
||||
|
</Field> |
||||
@ -0,0 +1,61 @@ |
|||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
|
||||
|
namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending |
||||
|
{ |
||||
|
public partial class SelectExtensionProperty<TEntity, TResourceType> : ComponentBase |
||||
|
where TEntity : IHasExtraProperties |
||||
|
{ |
||||
|
protected List<SelectItem<int>> SelectItems = new (); |
||||
|
|
||||
|
[Inject] public IStringLocalizerFactory StringLocalizerFactory { get; set; } |
||||
|
|
||||
|
[Parameter] public TEntity Entity { get; set; } |
||||
|
|
||||
|
[Parameter] public ObjectExtensionPropertyInfo PropertyInfo { get; set; } |
||||
|
|
||||
|
public int SelectedValue |
||||
|
{ |
||||
|
get { return Entity.GetProperty<int>(PropertyInfo.Name); } |
||||
|
set { Entity.SetProperty(PropertyInfo.Name, value, false); } |
||||
|
} |
||||
|
|
||||
|
protected virtual List<SelectItem<int>> GetSelectItemsFromEnum() |
||||
|
{ |
||||
|
var selectItems = new List<SelectItem<int>>(); |
||||
|
|
||||
|
foreach (var enumValue in PropertyInfo.Type.GetEnumValues()) |
||||
|
{ |
||||
|
selectItems.Add( new SelectItem<int> |
||||
|
{ |
||||
|
Value = (int) enumValue, |
||||
|
Text = EnumHelper.GetLocalizedMemberName(PropertyInfo.Type, enumValue, StringLocalizerFactory) |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
return selectItems; |
||||
|
} |
||||
|
|
||||
|
protected override void OnParametersSet() |
||||
|
{ |
||||
|
SelectItems = GetSelectItemsFromEnum(); |
||||
|
StateHasChanged(); |
||||
|
|
||||
|
if (!Entity.HasProperty(PropertyInfo.Name)) |
||||
|
{ |
||||
|
SelectedValue = (int)PropertyInfo.Type.GetEnumValues().GetValue(0); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class SelectItem<TValue> |
||||
|
{ |
||||
|
public string Text { get; set; } |
||||
|
public TValue Value { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
@typeparam TEntity |
||||
|
@typeparam TResourceType |
||||
|
@using Volo.Abp.BlazoriseUI |
||||
|
@using Volo.Abp.Localization |
||||
|
|
||||
|
@if (PropertyInfo != null && Entity != null) |
||||
|
{ |
||||
|
<Field> |
||||
|
<FieldLabel>@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)</FieldLabel> |
||||
|
<TextEdit @bind-Text="@Value" Role="@PropertyInfo.GetTextRole()" InputMode="@PropertyInfo.GetTextInputMode()"> |
||||
|
|
||||
|
</TextEdit> |
||||
|
</Field> |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
|
||||
|
namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending |
||||
|
{ |
||||
|
public partial class TextExtensionProperty<TEntity, TResourceType> : ComponentBase |
||||
|
where TEntity : IHasExtraProperties |
||||
|
{ |
||||
|
[Inject] |
||||
|
public IStringLocalizerFactory StringLocalizerFactory { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public TEntity Entity { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public ObjectExtensionPropertyInfo PropertyInfo { get; set; } |
||||
|
|
||||
|
|
||||
|
protected string Value |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return PropertyInfo.GetTextInputValueOrNull(Entity.GetProperty(PropertyInfo.Name)); |
||||
|
} |
||||
|
set |
||||
|
{ |
||||
|
Entity.SetProperty(PropertyInfo.Name, value, validate: false); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
@typeparam TEntity |
||||
|
@typeparam TResourceType |
||||
|
@using Volo.Abp.BlazoriseUI |
||||
|
@using Volo.Abp.Localization |
||||
|
|
||||
|
@if (PropertyInfo != null && Entity != null) |
||||
|
{ |
||||
|
<Field> |
||||
|
<FieldLabel>@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)</FieldLabel>--> |
||||
|
<TimeEdit TValue="TimeSpan?" @bind-Time="@Value"> |
||||
|
</TimeEdit> |
||||
|
</Field> |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
|
||||
|
namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending |
||||
|
{ |
||||
|
public partial class TimeExtensionProperty<TEntity, TResourceType> : ComponentBase |
||||
|
where TEntity : IHasExtraProperties |
||||
|
{ |
||||
|
[Inject] |
||||
|
public IStringLocalizerFactory StringLocalizerFactory { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public TEntity Entity { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public ObjectExtensionPropertyInfo PropertyInfo { get; set; } |
||||
|
|
||||
|
protected TimeSpan? Value |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return PropertyInfo.GetInputValueOrDefault<TimeSpan?>(Entity.GetProperty(PropertyInfo.Name)); |
||||
|
} |
||||
|
set |
||||
|
{ |
||||
|
Entity.SetProperty(PropertyInfo.Name, value, false); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,29 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
using Blazorise; |
|
||||
using Microsoft.AspNetCore.Components; |
|
||||
|
|
||||
namespace Volo.Abp.BlazoriseUI.Components |
|
||||
{ |
|
||||
public partial class PageHeader : ComponentBase |
|
||||
{ |
|
||||
[Parameter] |
|
||||
public string Title { get; set; } |
|
||||
|
|
||||
[Parameter] |
|
||||
public bool BreadcrumbShowHome { get; set; } = true; |
|
||||
|
|
||||
[Parameter] |
|
||||
public bool BreadcrumbShowCurrent { get; set; } = true; |
|
||||
|
|
||||
[Parameter] |
|
||||
public RenderFragment ChildContent { get; set; } |
|
||||
|
|
||||
[Parameter] |
|
||||
public List<BreadcrumbItem> BreadcrumbItems { get; set; } |
|
||||
|
|
||||
public PageHeader() |
|
||||
{ |
|
||||
BreadcrumbItems = new List<BreadcrumbItem>(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,7 @@ |
|||||
|
<Button Color="@Color" Clicked="@Clicked" Disabled="@Disabled"> |
||||
|
@if (Icon != null) |
||||
|
{ |
||||
|
<Icon Name="IconName.Add" Class="mr-1"></Icon> |
||||
|
} |
||||
|
@Text |
||||
|
</Button> |
||||
@ -0,0 +1,25 @@ |
|||||
|
using Blazorise; |
||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.BlazoriseUI.Components |
||||
|
{ |
||||
|
public partial class ToolbarButton : ComponentBase |
||||
|
{ |
||||
|
[Parameter] |
||||
|
public Color Color { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public object Icon { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public string Text { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public Func<Task> Clicked { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public bool Disabled { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.ObjectExtending |
||||
|
{ |
||||
|
public static class ObjectExtensionPropertyInfoBlazorExtensions |
||||
|
{ |
||||
|
private static readonly Type[] DateTimeTypes = |
||||
|
{ |
||||
|
typeof(DateTime), |
||||
|
typeof(DateTime?), |
||||
|
typeof(DateTimeOffset), |
||||
|
typeof(DateTimeOffset?) |
||||
|
}; |
||||
|
|
||||
|
public static bool IsDate(this IBasicObjectExtensionPropertyInfo property) |
||||
|
{ |
||||
|
return DateTimeTypes.Contains(property.Type) && |
||||
|
property.GetDataTypeOrNull() == DataType.Date; |
||||
|
} |
||||
|
|
||||
|
public static bool IsDateTime(this IBasicObjectExtensionPropertyInfo property) |
||||
|
{ |
||||
|
return DateTimeTypes.Contains(property.Type) && |
||||
|
!property.IsDate(); |
||||
|
} |
||||
|
|
||||
|
public static DataType? GetDataTypeOrNull(this IBasicObjectExtensionPropertyInfo property) |
||||
|
{ |
||||
|
return property |
||||
|
.Attributes |
||||
|
.OfType<DataTypeAttribute>() |
||||
|
.FirstOrDefault()?.DataType; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
@using System; |
||||
|
@using Volo.Abp.Identity |
||||
|
@using Microsoft.Extensions.Localization |
||||
|
@using Volo.Abp.Identity.Localization |
||||
|
|
||||
|
@inject IStringLocalizer<IdentityResource> L |
||||
|
|
||||
|
@(Data.As<IdentityRoleDto>().Name) |
||||
|
@if (Data.As<IdentityRoleDto>().IsDefault) |
||||
|
{ |
||||
|
<Badge Color="Color.Primary" Margin="Margin.Is1.FromLeft">@L["DisplayName:IsDefault"]</Badge> |
||||
|
} |
||||
|
@if (Data.As<IdentityRoleDto>().IsPublic) |
||||
|
{ |
||||
|
<Badge Color="Color.Light" Margin="Margin.Is1.FromLeft">@L["DisplayName:IsPublic"]</Badge> |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Microsoft.AspNetCore.Components; |
||||
|
|
||||
|
namespace Volo.Abp.Identity.Blazor.Pages.Identity |
||||
|
{ |
||||
|
public partial class RoleNameComponent : ComponentBase |
||||
|
{ |
||||
|
[Parameter] public object Data { get; set; } |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue