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