28 changed files with 893 additions and 50 deletions
@ -0,0 +1,259 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using System.Linq; |
||||
|
using Lsw.Abp.AntDesignUI.Components.ObjectExtending; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
using Volo.Abp.Reflection; |
||||
|
|
||||
|
namespace Lsw.Abp.AntDesignUI; |
||||
|
|
||||
|
public static class AntDesignUiObjectExtensionPropertyInfoExtensions |
||||
|
{ |
||||
|
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-dd HH: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 string GetTextInputMode(this ObjectExtensionPropertyInfo propertyInfo) |
||||
|
{ |
||||
|
foreach (var attribute in propertyInfo.Attributes) |
||||
|
{ |
||||
|
var textRoleByAttribute = GetTextInputModeFromAttributeOrNull(attribute); |
||||
|
if (textRoleByAttribute != null) |
||||
|
{ |
||||
|
return textRoleByAttribute; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return GetTextInputModeFromTypeOrNull(propertyInfo.Type) |
||||
|
?? "text"; //default
|
||||
|
} |
||||
|
|
||||
|
private static string GetTextInputModeFromTypeOrNull(Type type) |
||||
|
{ |
||||
|
// if (TypeHelper.IsFloatingType(type))
|
||||
|
// {
|
||||
|
// return "number";
|
||||
|
// }
|
||||
|
|
||||
|
if (NumberTypes.Contains(type)) |
||||
|
{ |
||||
|
return "number"; |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
private static string GetTextInputModeFromAttributeOrNull(Attribute attribute) |
||||
|
{ |
||||
|
if (attribute is EmailAddressAttribute) |
||||
|
{ |
||||
|
return "email"; |
||||
|
} |
||||
|
|
||||
|
if (attribute is UrlAttribute) |
||||
|
{ |
||||
|
return "url"; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
if (attribute is PhoneAttribute) |
||||
|
{ |
||||
|
return "tel"; |
||||
|
} |
||||
|
|
||||
|
if (attribute is DataTypeAttribute dataTypeAttribute) |
||||
|
{ |
||||
|
switch (dataTypeAttribute.DataType) |
||||
|
{ |
||||
|
case DataType.EmailAddress: |
||||
|
return "email"; |
||||
|
case DataType.Url: |
||||
|
return "url"; |
||||
|
case DataType.PhoneNumber: |
||||
|
return "tel"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public static string GetTextRole(this ObjectExtensionPropertyInfo propertyInfo) |
||||
|
{ |
||||
|
foreach (var attribute in propertyInfo.Attributes) |
||||
|
{ |
||||
|
var textRoleByAttribute = GetTextRoleFromAttributeOrNull(attribute); |
||||
|
if (textRoleByAttribute != null) |
||||
|
{ |
||||
|
return textRoleByAttribute; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return "text"; //default
|
||||
|
} |
||||
|
|
||||
|
private static string GetTextRoleFromAttributeOrNull(Attribute attribute) |
||||
|
{ |
||||
|
if (attribute is EmailAddressAttribute) |
||||
|
{ |
||||
|
return "email"; |
||||
|
} |
||||
|
|
||||
|
if (attribute is UrlAttribute) |
||||
|
{ |
||||
|
return "url"; |
||||
|
} |
||||
|
|
||||
|
if (attribute is DataTypeAttribute dataTypeAttribute) |
||||
|
{ |
||||
|
switch (dataTypeAttribute.DataType) |
||||
|
{ |
||||
|
case DataType.Password: |
||||
|
return "password"; |
||||
|
case DataType.EmailAddress: |
||||
|
return "email"; |
||||
|
case DataType.Url: |
||||
|
return "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,13 @@ |
|||||
|
@typeparam TEntity |
||||
|
@typeparam TResourceType |
||||
|
@using Volo.Abp.Localization |
||||
|
@inherits ExtensionPropertyComponentBase<TEntity, TResourceType> |
||||
|
|
||||
|
@if (PropertyInfo != null && Entity != null) |
||||
|
{ |
||||
|
<FormItem> |
||||
|
<Checkbox @bind-Value="@Value"> |
||||
|
@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory) |
||||
|
</Checkbox> |
||||
|
</FormItem> |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using Volo.Abp.Data; |
||||
|
|
||||
|
namespace Lsw.Abp.AntDesignUI.Components.ObjectExtending; |
||||
|
|
||||
|
public partial class CheckExtensionProperty<TEntity, TResourceType> |
||||
|
where TEntity : IHasExtraProperties |
||||
|
{ |
||||
|
protected bool Value { |
||||
|
get { |
||||
|
return PropertyInfo.GetInputValueOrDefault<bool>(Entity.GetProperty(PropertyInfo.Name)); |
||||
|
} |
||||
|
set { |
||||
|
Entity.SetProperty(PropertyInfo.Name, value, false); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
@typeparam TEntity |
||||
|
@typeparam TResourceType |
||||
|
@using Volo.Abp.Localization |
||||
|
@inherits ExtensionPropertyComponentBase<TEntity, TResourceType> |
||||
|
|
||||
|
@if (PropertyInfo != null && Entity != null) |
||||
|
{ |
||||
|
<FormItem Label="@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"> |
||||
|
<DatePicker |
||||
|
@bind-Value="@Value" |
||||
|
Picker="@DatePickerType.Date" |
||||
|
ShowTime="@PropertyInfo.IsDateTime()" |
||||
|
Format="@PropertyInfo.GetDateEditInputFormatOrNull().RemovePreFix("{0:").RemovePostFix("}")"/> |
||||
|
</FormItem> |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Data; |
||||
|
|
||||
|
namespace Lsw.Abp.AntDesignUI.Components.ObjectExtending; |
||||
|
|
||||
|
public partial class DateTimeExtensionProperty<TEntity, TResourceType> |
||||
|
where TEntity : IHasExtraProperties |
||||
|
{ |
||||
|
protected DateTime? Value { |
||||
|
get { |
||||
|
return PropertyInfo.GetInputValueOrDefault<DateTime?>(Entity.GetProperty(PropertyInfo.Name)); |
||||
|
} |
||||
|
set { |
||||
|
Entity.SetProperty(PropertyInfo.Name, value, false); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
using System; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace Lsw.Abp.AntDesignUI.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,27 @@ |
|||||
|
@typeparam TEntityType |
||||
|
@typeparam TResourceType |
||||
|
@using Volo.Abp.ObjectExtending |
||||
|
@using Volo.Abp.Data |
||||
|
|
||||
|
@{ |
||||
|
Entity.SetDefaultsForExtraProperties(); |
||||
|
|
||||
|
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" LH="@LH" /> |
||||
|
} |
||||
|
else if (!propertyInfo.Lookup.Url.IsNullOrEmpty()) |
||||
|
{ |
||||
|
<LookupExtensionProperty PropertyInfo="@propertyInfo" Entity="@Entity" TEntity="TEntityType" TResourceType="TResourceType" LH="@LH" /> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
@ExtensionPropertyRender(propertyInfo) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
using Volo.Abp.AspNetCore.Components.Web; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
|
||||
|
namespace Lsw.Abp.AntDesignUI.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; } |
||||
|
|
||||
|
private RenderFragment ExtensionPropertyRender(ObjectExtensionPropertyInfo propertyInfo) => builder => |
||||
|
{ |
||||
|
var inputType = propertyInfo.GetInputType(); |
||||
|
builder.OpenComponent(0, inputType.MakeGenericType(typeof(TEntityType), typeof(TResourceType))); |
||||
|
builder.AddAttribute(1, "PropertyInfo", propertyInfo); |
||||
|
builder.AddAttribute(2, "Entity", Entity); |
||||
|
builder.AddAttribute(3, "LH", LH); |
||||
|
builder.CloseComponent(); |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,76 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Microsoft.Extensions.Localization; |
||||
|
using Volo.Abp.AspNetCore.Components.Web; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
|
||||
|
namespace Lsw.Abp.AntDesignUI.Components.ObjectExtending; |
||||
|
|
||||
|
public abstract class ExtensionPropertyComponentBase<TEntity, TResourceType> : OwningComponentBase |
||||
|
where TEntity : IHasExtraProperties |
||||
|
{ |
||||
|
[Inject] |
||||
|
public IStringLocalizerFactory StringLocalizerFactory { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public TEntity Entity { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public ObjectExtensionPropertyInfo PropertyInfo { get; set; } |
||||
|
|
||||
|
[Parameter] |
||||
|
public AbpBlazorMessageLocalizerHelper<TResourceType> LH { get; set; } |
||||
|
//
|
||||
|
// protected virtual void Validate(ValidatorEventArgs e)
|
||||
|
// {
|
||||
|
// e.Status = ValidationStatus.Success;
|
||||
|
//
|
||||
|
// var validationAttributes = PropertyInfo.GetValidationAttributes();
|
||||
|
// var validationContext = new ValidationContext(Entity)
|
||||
|
// {
|
||||
|
// DisplayName = PropertyInfo.Name,
|
||||
|
// MemberName = PropertyInfo.Name
|
||||
|
// };
|
||||
|
//
|
||||
|
// foreach (var validationAttribute in validationAttributes)
|
||||
|
// {
|
||||
|
// var result = validationAttribute.GetValidationResult(e.Value, validationContext);
|
||||
|
// if (result == ValidationResult.Success || result == null)
|
||||
|
// {
|
||||
|
// continue;
|
||||
|
// }
|
||||
|
//
|
||||
|
// var errorMessage = result.ErrorMessage;
|
||||
|
// if (LH != null)
|
||||
|
// {
|
||||
|
// var formattedErrorMessage = GetDefaultErrorMessage(validationAttribute);
|
||||
|
// var errorMessageString = ValidationAttributeHelper.RevertErrorMessagePlaceholders(formattedErrorMessage);
|
||||
|
// var errorMessageArguments = ValidationMessageLocalizerAttributeFinder.FindAll(errorMessage, errorMessageString)
|
||||
|
// ?.OrderBy(x => x.Index)
|
||||
|
// ?.Select(x => x.Argument);
|
||||
|
//
|
||||
|
// errorMessage = LH.Localize(errorMessageString, errorMessageArguments);
|
||||
|
// }
|
||||
|
//
|
||||
|
// e.MemberNames = result.MemberNames;
|
||||
|
// e.Status = ValidationStatus.Error;
|
||||
|
// e.ErrorText = errorMessage;
|
||||
|
// break;
|
||||
|
// }
|
||||
|
// }
|
||||
|
//
|
||||
|
// private static string GetDefaultErrorMessage(ValidationAttribute validationAttribute)
|
||||
|
// {
|
||||
|
// if (validationAttribute is StringLengthAttribute stringLengthAttribute && stringLengthAttribute.MinimumLength != 0)
|
||||
|
// {
|
||||
|
// var nullable = ValidationAttributeHelper.ValidationAttributeCustomErrorMessageSetProperty.GetValue((object) validationAttribute) as bool?;
|
||||
|
// var flag = true;
|
||||
|
// if (!(nullable.GetValueOrDefault() == flag & nullable.HasValue))
|
||||
|
// {
|
||||
|
// return ValidationAttributeHelper.SetErrorMessagePlaceholders("The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.");
|
||||
|
// }
|
||||
|
// }
|
||||
|
// return ValidationAttributeHelper.SetErrorMessagePlaceholders(ValidationAttributeHelper.ValidationAttributeErrorMessageStringProperty.GetValue((object) validationAttribute) as string);
|
||||
|
// }
|
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
@typeparam TEntity |
||||
|
@typeparam TResourceType |
||||
|
@using Volo.Abp.Localization |
||||
|
@inherits ExtensionPropertyComponentBase<TEntity, TResourceType> |
||||
|
|
||||
|
<FormItem Label="@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"> |
||||
|
<AutoComplete @bind-Value="@SelectedValue" |
||||
|
CompareWith="@_compareWith" |
||||
|
Options="@lookupItems" |
||||
|
OnSelectionChange="SelectedValueChanged"> |
||||
|
<OptionTemplate Context="option"> |
||||
|
<AutoCompleteOption Value="@option.Value" Label="@option.Value.Text"> |
||||
|
</AutoCompleteOption> |
||||
|
</OptionTemplate> |
||||
|
</AutoComplete> |
||||
|
</FormItem> |
||||
@ -0,0 +1,91 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text.Json; |
||||
|
using System.Threading.Tasks; |
||||
|
using AntDesign; |
||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Volo.Abp.AspNetCore.Components.Web.Extensibility; |
||||
|
using Volo.Abp.Data; |
||||
|
|
||||
|
namespace Lsw.Abp.AntDesignUI.Components.ObjectExtending; |
||||
|
|
||||
|
public partial class LookupExtensionProperty<TEntity, TResourceType> |
||||
|
where TEntity : IHasExtraProperties |
||||
|
{ |
||||
|
protected List<SelectItem<object>> lookupItems; |
||||
|
|
||||
|
[Inject] public ILookupApiRequestService LookupApiService { get; set; } |
||||
|
|
||||
|
public string TextPropertyName => PropertyInfo.Name + "_Text"; |
||||
|
|
||||
|
private string SelectedValue { get; set; } |
||||
|
|
||||
|
private Func<object, object, bool> _compareWith = (a, b) => |
||||
|
{ |
||||
|
if (a is SelectItem<object> o1 && b is SelectItem<object> o2) |
||||
|
{ |
||||
|
return o1.Value == o2.Value; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
}; |
||||
|
|
||||
|
public LookupExtensionProperty() |
||||
|
{ |
||||
|
lookupItems = new List<SelectItem<object>>(); |
||||
|
} |
||||
|
|
||||
|
protected override async Task OnInitializedAsync() |
||||
|
{ |
||||
|
await base.OnInitializedAsync(); |
||||
|
await SearchFilterChangedAsync(string.Empty); |
||||
|
|
||||
|
SelectedValue = Entity.GetProperty(TextPropertyName)?.ToString(); |
||||
|
} |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
|
||||
|
private void SelectedValueChanged(AutoCompleteOption selectedItem) |
||||
|
{ |
||||
|
var selectedObject = (selectedItem.Value as SelectItem<object>)?.Value; |
||||
|
Entity.SetProperty(PropertyInfo.Name, selectedObject, false); |
||||
|
UpdateLookupTextProperty(selectedObject); |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task SearchFilterChangedAsync(string filter) |
||||
|
{ |
||||
|
lookupItems = await GetLookupItemsAsync(filter); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
@typeparam TEntity |
||||
|
@typeparam TResourceType |
||||
|
@using Volo.Abp.Localization |
||||
|
@inherits ExtensionPropertyComponentBase<TEntity, TResourceType> |
||||
|
|
||||
|
<FormItem Label="@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"> |
||||
|
<Select DataSource="@SelectItems" |
||||
|
@bind-Value="@SelectedValue" |
||||
|
ValueName="@nameof(SelectItem<int>.Value)" |
||||
|
LabelName="@nameof(SelectItem<int>.Text)"> |
||||
|
</Select> |
||||
|
</FormItem> |
||||
@ -0,0 +1,53 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Data; |
||||
|
|
||||
|
namespace Lsw.Abp.AntDesignUI.Components.ObjectExtending; |
||||
|
|
||||
|
public partial class SelectExtensionProperty<TEntity, TResourceType> |
||||
|
where TEntity : IHasExtraProperties |
||||
|
{ |
||||
|
protected List<SelectItem<int>> SelectItems = new(); |
||||
|
|
||||
|
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; } |
||||
|
|
||||
|
public override string ToString() |
||||
|
{ |
||||
|
return Text; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
@typeparam TEntity |
||||
|
@typeparam TResourceType |
||||
|
@using Volo.Abp.Localization |
||||
|
@inherits ExtensionPropertyComponentBase<TEntity, TResourceType> |
||||
|
|
||||
|
@if (PropertyInfo != null && Entity != null) |
||||
|
{ |
||||
|
<FormItem Label="@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"> |
||||
|
<Input @bind-Value="@Value" Type="@PropertyInfo.GetTextInputMode()"/> |
||||
|
</FormItem> |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using Volo.Abp.Data; |
||||
|
|
||||
|
namespace Lsw.Abp.AntDesignUI.Components.ObjectExtending; |
||||
|
|
||||
|
public partial class TextExtensionProperty<TEntity, TResourceType> |
||||
|
where TEntity : IHasExtraProperties |
||||
|
{ |
||||
|
protected string Value { |
||||
|
get { |
||||
|
return PropertyInfo.GetTextInputValueOrNull(Entity.GetProperty(PropertyInfo.Name)); |
||||
|
} |
||||
|
set { |
||||
|
Entity.SetProperty(PropertyInfo.Name, value, validate: false); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
@typeparam TEntity |
||||
|
@typeparam TResourceType |
||||
|
@using Volo.Abp.Localization |
||||
|
@inherits ExtensionPropertyComponentBase<TEntity, TResourceType> |
||||
|
|
||||
|
@if (PropertyInfo != null && Entity != null) |
||||
|
{ |
||||
|
<FormItem Label="@PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"> |
||||
|
<TimePicker @bind-Value="@Value"/> |
||||
|
</FormItem> |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Data; |
||||
|
|
||||
|
namespace Lsw.Abp.AntDesignUI.Components.ObjectExtending; |
||||
|
|
||||
|
public partial class TimeExtensionProperty<TEntity, TResourceType> |
||||
|
where TEntity : IHasExtraProperties |
||||
|
{ |
||||
|
protected TimeSpan? Value { |
||||
|
get { |
||||
|
return PropertyInfo.GetInputValueOrDefault<TimeSpan?>(Entity.GetProperty(PropertyInfo.Name)); |
||||
|
} |
||||
|
set { |
||||
|
Entity.SetProperty(PropertyInfo.Name, value, false); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
using System; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
|
||||
|
namespace Lsw.Abp.AntDesignUI; |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue