Browse Source

feat: implements property extension

pull/5/head
rqx110 4 years ago
parent
commit
d63e25653a
  1. 4
      modules/IdentityManagement/Lsw.Abp.IdentityManagement.Blazor.AntDesignUI/Pages/RoleManagement.razor
  2. 20
      modules/IdentityManagement/Lsw.Abp.IdentityManagement.Blazor.AntDesignUI/Pages/RoleManagement.razor.cs
  3. 37
      modules/IdentityManagement/Lsw.Abp.IdentityManagement.Blazor.AntDesignUI/Pages/UserManagement.razor
  4. 17
      modules/IdentityManagement/Lsw.Abp.IdentityManagement.Blazor.AntDesignUI/Pages/UserManagement.razor.cs
  5. 1
      modules/IdentityManagement/Lsw.Abp.IdentityManagement.Blazor.AntDesignUI/_Imports.razor
  6. 6
      modules/TenantManagement/Lsw.Abp.TenantManagement.Blazor.AntDesignUI/Pages/TenantManagement.razor
  7. 20
      modules/TenantManagement/Lsw.Abp.TenantManagement.Blazor.AntDesignUI/Pages/TenantManagement.razor.cs
  8. 1
      modules/TenantManagement/Lsw.Abp.TenantManagement.Blazor.AntDesignUI/_Imports.razor
  9. 46
      src/Lsw.Abp.AntDesignUI/AbpCrudPageBase.cs
  10. 259
      src/Lsw.Abp.AntDesignUI/AntDesignUiObjectExtensionPropertyInfoExtensions.cs
  11. 46
      src/Lsw.Abp.AntDesignUI/Components/AbpExtensibleDataGrid.razor
  12. 13
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/CheckExtensionProperty.razor
  13. 16
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/CheckExtensionProperty.razor.cs
  14. 15
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/DateTimeExtensionProperty.razor
  15. 17
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/DateTimeExtensionProperty.razor.cs
  16. 28
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/EnumHelper.cs
  17. 27
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/ExtensionProperties.razor
  18. 30
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/ExtensionProperties.razor.cs
  19. 76
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/ExtensionPropertyComponentBase.cs
  20. 16
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/LookupExtensionProperty.razor
  21. 91
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/LookupExtensionProperty.razor.cs
  22. 12
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/SelectExtensionProperty.razor
  23. 53
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/SelectExtensionProperty.razor.cs
  24. 11
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/TextExtensionProperty.razor
  25. 16
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/TextExtensionProperty.razor.cs
  26. 11
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/TimeExtensionProperty.razor
  27. 17
      src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/TimeExtensionProperty.razor.cs
  28. 37
      src/Lsw.Abp.AntDesignUI/ObjectExtensionPropertyInfoBlazorExtensions.cs

4
modules/IdentityManagement/Lsw.Abp.IdentityManagement.Blazor.AntDesignUI/Pages/RoleManagement.razor

@ -32,6 +32,7 @@
<FormItem Label="@L["DisplayName:RoleName"]">
<Input @bind-Value="@context.Name"/>
</FormItem>
<ExtensionProperties TEntityType="IdentityRoleCreateDto" TResourceType="IdentityResource" Entity="@NewEntity" LH="@LH"/>
<FormItem>
<Checkbox @bind-Value="context.IsDefault">@L["DisplayName:IsDefault"]</Checkbox>
</FormItem>
@ -53,6 +54,7 @@
<FormItem Label="@L["DisplayName:RoleName"]">
<Input @bind-Value="@context.Name"/>
</FormItem>
<ExtensionProperties TEntityType="IdentityRoleUpdateDto" TResourceType="IdentityResource" Entity="@EditingEntity" LH="@LH"/>
<FormItem>
<Checkbox @bind-Value="context.IsDefault">@L["DisplayName:IsDefault"]</Checkbox>
</FormItem>
@ -67,4 +69,4 @@
@if (HasManagePermissionsPermission)
{
<PermissionManagementModal @ref="PermissionManagementModal"/>
}
}

20
modules/IdentityManagement/Lsw.Abp.IdentityManagement.Blazor.AntDesignUI/Pages/RoleManagement.razor.cs

@ -10,6 +10,7 @@ using Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions;
using Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns;
using Volo.Abp.Identity;
using Volo.Abp.Identity.Localization;
using Volo.Abp.ObjectExtending;
namespace Lsw.Abp.IdentityManagement.Blazor.AntDesignUI.Pages;
@ -90,19 +91,18 @@ public partial class RoleManagement
Title = L["RoleName"],
Data = nameof(IdentityRoleDto.Name),
Component = typeof(RoleNameComponent)
},
new TableColumn
{
Title = L["Actions"],
Actions = EntityActions.Get<RoleManagement>()
},
}
});
RoleManagementTableColumns.AddRange(GetExtensionTableColumns(IdentityModuleExtensionConsts.ModuleName,
IdentityModuleExtensionConsts.EntityNames.Role));
RoleManagementTableColumns.Add(new TableColumn
{
Title = L["Actions"],
Actions = EntityActions.Get<RoleManagement>()
});
//TODO Implement object extensions
// RoleManagementTableColumns.AddRange(GetExtensionTableColumns(IdentityModuleExtensionConsts.ModuleName,
// IdentityModuleExtensionConsts.EntityNames.Role));
return base.SetTableColumnsAsync();
}

37
modules/IdentityManagement/Lsw.Abp.IdentityManagement.Blazor.AntDesignUI/Pages/UserManagement.razor

@ -41,7 +41,7 @@
<Input @bind-Value="@context.Surname"/>
</FormItem>
<FormItem Label="@L["DisplayName:Password"]">
<InputPassword @bind-Value="@context.Password"/>
<InputPassword @bind-Value="@context.Password"/>
</FormItem>
<FormItem Label="@L["DisplayName:Email"]">
<Input @bind-Value="@context.Email"/>
@ -55,15 +55,16 @@
<FormItem>
<Checkbox @bind-Value="context.LockoutEnabled">@L["DisplayName:LockoutEnabled"]</Checkbox>
</FormItem>
<ExtensionProperties TEntityType="IdentityUserCreateDto" TResourceType="IdentityResource" Entity="@NewEntity" LH="@LH"/>
</TabPane>
<TabPane Tab="@L["Roles"]">
@foreach (var role in NewUserRoles)
{
<FormItem WrapperColOffset="2">
<Checkbox @bind-Value="role.IsAssigned">@role.Name</Checkbox>
</FormItem>
}
@foreach (var role in NewUserRoles)
{
<FormItem WrapperColOffset="2">
<Checkbox @bind-Value="role.IsAssigned">@role.Name</Checkbox>
</FormItem>
}
</TabPane>
</Tabs>
}
@ -92,7 +93,7 @@
<Input @bind-Value="@context.Surname"/>
</FormItem>
<FormItem Label="@L["DisplayName:Password"]">
<InputPassword @bind-Value="@context.Password"/>
<InputPassword @bind-Value="@context.Password"/>
</FormItem>
<FormItem Label="@L["DisplayName:Email"]">
<Input @bind-Value="@context.Email"/>
@ -106,15 +107,17 @@
<FormItem>
<Checkbox @bind-Value="context.LockoutEnabled">@L["DisplayName:LockoutEnabled"]</Checkbox>
</FormItem>
<ExtensionProperties TEntityType="IdentityUserUpdateDto" TResourceType="IdentityResource" Entity="@EditingEntity" LH="@LH"/>
</TabPane>
<TabPane Tab="@L["Roles"]">
@foreach (var role in EditUserRoles)
{
<FormItem WrapperColOffset="2">
<Checkbox @bind-Value="role.IsAssigned">@role.Name</Checkbox>
</FormItem>
}
@foreach (var role in EditUserRoles)
{
<FormItem WrapperColOffset="2">
<Checkbox @bind-Value="role.IsAssigned">@role.Name</Checkbox>
</FormItem>
}
</TabPane>
</Tabs>
}
@ -126,4 +129,4 @@
@if (HasManagePermissionsPermission)
{
<PermissionManagementModal @ref="PermissionManagementModal"/>
}
}

17
modules/IdentityManagement/Lsw.Abp.IdentityManagement.Blazor.AntDesignUI/Pages/UserManagement.razor.cs

@ -11,6 +11,7 @@ using Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions;
using Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns;
using Volo.Abp.Identity;
using Volo.Abp.Identity.Localization;
using Volo.Abp.ObjectExtending;
namespace Lsw.Abp.IdentityManagement.Blazor.AntDesignUI.Pages;
@ -177,14 +178,18 @@ public partial class UserManagement
{
Title = L["PhoneNumber"],
Data = nameof(IdentityUserDto.PhoneNumber),
},
new TableColumn
{
Title = L["Actions"],
Actions = EntityActions.Get<UserManagement>()
},
}
});
UserManagementTableColumns.AddRange(GetExtensionTableColumns(IdentityModuleExtensionConsts.ModuleName,
IdentityModuleExtensionConsts.EntityNames.User));
UserManagementTableColumns.Add(new TableColumn
{
Title = L["Actions"],
Actions = EntityActions.Get<UserManagement>()
});
return base.SetEntityActionsAsync();
}

1
modules/IdentityManagement/Lsw.Abp.IdentityManagement.Blazor.AntDesignUI/_Imports.razor

@ -2,6 +2,7 @@
@using Volo.Abp.AspNetCore.Components.Web
@using Lsw.Abp.AntDesignUI
@using Lsw.Abp.AntDesignUI.Components
@using Lsw.Abp.AntDesignUI.Components.ObjectExtending
@using AntDesign
@using AntDesign.TableModels
@using Lsw.Abp.AspnetCore.Components.Web.AntDesignTheme.Layout

6
modules/TenantManagement/Lsw.Abp.TenantManagement.Blazor.AntDesignUI/Pages/TenantManagement.razor

@ -39,7 +39,7 @@
<FormItem Label="@L["DisplayName:AdminPassword"]">
<InputPassword @bind-Value="@context.AdminPassword"/>
</FormItem>
<ExtensionProperties TEntityType="TenantCreateDto" TResourceType="AbpTenantManagementResource" Entity="@NewEntity" LH="@LH"/>
</Form>
</Modal>
}
@ -55,7 +55,7 @@
<FormItem Label="@L["TenantName"]">
<Input @bind-Value="@context.Name"/>
</FormItem>
<ExtensionProperties TEntityType="TenantUpdateDto" TResourceType="AbpTenantManagementResource" Entity="@EditingEntity" LH="@LH"/>
</Form>
</Modal>
}
@ -63,4 +63,4 @@
@if (HasManageFeaturesPermission)
{
<FeatureManagementModal @ref="FeatureManagementModal"/>
}
}

20
modules/TenantManagement/Lsw.Abp.TenantManagement.Blazor.AntDesignUI/Pages/TenantManagement.razor.cs

@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Authorization;
using Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions;
using Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns;
using Volo.Abp.FeatureManagement;
using Volo.Abp.ObjectExtending;
using Volo.Abp.TenantManagement;
using Volo.Abp.TenantManagement.Localization;
@ -117,18 +118,19 @@ public partial class TenantManagement
{
Title = L["TenantName"],
Data = nameof(TenantDto.Name),
},
new TableColumn
{
Title = L["Actions"],
Actions = EntityActions.Get<TenantManagement>()
},
}
});
// TenantManagementTableColumns.AddRange(GetExtensionTableColumns(
// TenantManagementModuleExtensionConsts.ModuleName,
// TenantManagementModuleExtensionConsts.EntityNames.Tenant));
TenantManagementTableColumns.AddRange(GetExtensionTableColumns(
TenantManagementModuleExtensionConsts.ModuleName,
TenantManagementModuleExtensionConsts.EntityNames.Tenant));
TenantManagementTableColumns.Add(new TableColumn
{
Title = L["Actions"],
Actions = EntityActions.Get<TenantManagement>()
});
return base.SetTableColumnsAsync();
}
}

1
modules/TenantManagement/Lsw.Abp.TenantManagement.Blazor.AntDesignUI/_Imports.razor

@ -3,5 +3,6 @@
@using AntDesign
@using Lsw.Abp.AntDesignUI
@using Lsw.Abp.AntDesignUI.Components
@using Lsw.Abp.AntDesignUI.Components.ObjectExtending
@using Lsw.Abp.FeatureManagement.Blazor.AntDesignUI.Components
@using Lsw.Abp.AspnetCore.Components.Web.AntDesignTheme.Layout

46
src/Lsw.Abp.AntDesignUI/AbpCrudPageBase.cs

@ -7,6 +7,7 @@ using AntDesign.TableModels;
using JetBrains.Annotations;
using Localization.Resources.AbpUi;
using Lsw.Abp.AntDesignUI.Components;
using Lsw.Abp.AntDesignUI.Components.ObjectExtending;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
@ -17,6 +18,9 @@ using Volo.Abp.AspNetCore.Components;
using Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions;
using Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns;
using Volo.Abp.Authorization;
using Volo.Abp.Localization;
using Volo.Abp.ObjectExtending;
using Volo.Abp.ObjectExtending.Modularity;
namespace Lsw.Abp.AntDesignUI;
@ -580,6 +584,48 @@ public abstract class AbpCrudPageBase<
{
return ValueTask.CompletedTask;
}
protected virtual IEnumerable<TableColumn> GetExtensionTableColumns(string moduleName, string entityType)
{
var properties = ModuleExtensionConfigurationHelper.GetPropertyConfigurations(moduleName, entityType);
foreach (var propertyInfo in properties)
{
if (propertyInfo.IsAvailableToClients && propertyInfo.UI.OnTable.IsVisible)
{
if (propertyInfo.Name.EndsWith("_Text"))
{
var lookupPropertyName = propertyInfo.Name.RemovePostFix("_Text");
var lookupPropertyDefinition = properties.SingleOrDefault(t => t.Name == lookupPropertyName);
yield return new TableColumn
{
Title = lookupPropertyDefinition.GetLocalizedDisplayName(StringLocalizerFactory),
Data = $"ExtraProperties[{propertyInfo.Name}]"
};
}
else
{
var column = new TableColumn
{
Title = propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory),
Data = $"ExtraProperties[{propertyInfo.Name}]"
};
if (propertyInfo.IsDate() || propertyInfo.IsDateTime())
{
column.DisplayFormat = propertyInfo.GetDateEditInputFormatOrNull();
}
if (propertyInfo.Type.IsEnum)
{
column.ValueConverter = (val) =>
EnumHelper.GetLocalizedMemberName(propertyInfo.Type, val.As<ExtensibleObject>().ExtraProperties[propertyInfo.Name], StringLocalizerFactory);
}
yield return column;
}
}
}
}
}

259
src/Lsw.Abp.AntDesignUI/AntDesignUiObjectExtensionPropertyInfoExtensions.cs

@ -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;
}
}

46
src/Lsw.Abp.AntDesignUI/Components/AbpExtensibleDataGrid.razor

@ -1,4 +1,5 @@
@typeparam TItem
@using Volo.Abp.Data
@typeparam TItem
<Table TItem="TItem"
DataSource="@Data"
@ -9,7 +10,9 @@
Total="TotalItems"
Class="@Class"
RemoteDataSource="true"
Responsive="@Responsive">
Responsive="@Responsive"
TableLayout=""
ScrollX="100%">
@if (Columns != null)
{
@ -17,7 +20,7 @@
{
if (column.Actions.Any())
{
<Column TData="object" Title="@column.Title" Fixed="true">
<Column TData="object" Title="@column.Title" Fixed="right">
<EntityActions TItem="TItem">
@foreach (var action in column.Actions)
{
@ -75,7 +78,42 @@
}
else
{
<Column TData="object" Title="@column.Title">
@{
var entity = context as IHasExtraProperties;
var propertyName = ExtensionPropertiesRegex.Match(column.Data).Groups[1].Value;
var propertyValue = entity.GetProperty(propertyName);
if (propertyValue is bool)
{
if ((bool) propertyValue)
{
<Icon Type="check" Theme="outline"/>
}
else
{
<Icon Type="close" Theme="outline"/>
}
}
else
{
if (column.ValueConverter != null)
{
@(GetConvertedFieldValue(context, column))
}
else
{
if (column.DisplayFormat == null)
{
@propertyValue
}
else
{
@string.Format(column.DisplayFormatProvider, column.DisplayFormat, propertyValue)
}
}
}
}
</Column>
}
}
}

13
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/CheckExtensionProperty.razor

@ -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>
}

16
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/CheckExtensionProperty.razor.cs

@ -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);
}
}
}

15
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/DateTimeExtensionProperty.razor

@ -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>
}

17
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/DateTimeExtensionProperty.razor.cs

@ -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);
}
}
}

28
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/EnumHelper.cs

@ -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;
}
}

27
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/ExtensionProperties.razor

@ -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)
}
}
}
}

30
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/ExtensionProperties.razor.cs

@ -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();
};
}

76
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/ExtensionPropertyComponentBase.cs

@ -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);
// }
}

16
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/LookupExtensionProperty.razor

@ -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>

91
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/LookupExtensionProperty.razor.cs

@ -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);
}
}

12
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/SelectExtensionProperty.razor

@ -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>

53
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/SelectExtensionProperty.razor.cs

@ -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;
}
}

11
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/TextExtensionProperty.razor

@ -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>
}

16
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/TextExtensionProperty.razor.cs

@ -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);
}
}
}

11
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/TimeExtensionProperty.razor

@ -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>
}

17
src/Lsw.Abp.AntDesignUI/Components/ObjectExtending/TimeExtensionProperty.razor.cs

@ -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);
}
}
}

37
src/Lsw.Abp.AntDesignUI/ObjectExtensionPropertyInfoBlazorExtensions.cs

@ -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…
Cancel
Save