mirror of https://github.com/abpframework/abp.git
188 changed files with 3634 additions and 693 deletions
@ -0,0 +1,178 @@ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.ObjectExtending; |
|||
using Volo.Abp.ObjectExtending.Modularity; |
|||
using Volo.Abp.Reflection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
public class CachedObjectExtensionsDtoService : ICachedObjectExtensionsDtoService, ISingletonDependency |
|||
{ |
|||
private volatile ObjectExtensionsDto _cachedValue; |
|||
private readonly object _syncLock = new object(); |
|||
|
|||
public virtual ObjectExtensionsDto Get() |
|||
{ |
|||
if (_cachedValue == null) |
|||
{ |
|||
lock (_syncLock) |
|||
{ |
|||
if (_cachedValue == null) |
|||
{ |
|||
_cachedValue = GenerateCacheValue(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return _cachedValue; |
|||
} |
|||
|
|||
protected virtual ObjectExtensionsDto GenerateCacheValue() |
|||
{ |
|||
var objectExtensionsDto = new ObjectExtensionsDto |
|||
{ |
|||
Modules = new Dictionary<string, ModuleExtensionDto>() |
|||
}; |
|||
|
|||
foreach (var moduleConfig in ObjectExtensionManager.Instance.Modules()) |
|||
{ |
|||
objectExtensionsDto.Modules[moduleConfig.Key] = CreateModuleExtensionDto(moduleConfig.Value); |
|||
} |
|||
|
|||
return objectExtensionsDto; |
|||
} |
|||
|
|||
protected virtual ModuleExtensionDto CreateModuleExtensionDto( |
|||
ModuleExtensionConfiguration moduleConfig) |
|||
{ |
|||
var moduleExtensionDto = new ModuleExtensionDto |
|||
{ |
|||
Entities = new Dictionary<string, EntityExtensionDto>() |
|||
}; |
|||
|
|||
foreach (var objectConfig in moduleConfig.Entities) |
|||
{ |
|||
moduleExtensionDto.Entities[objectConfig.Key] = GetEntityExtensionDto(objectConfig.Value); |
|||
} |
|||
|
|||
foreach (var customConfig in moduleConfig.Configuration.Where(c => !c.Key.StartsWith("_"))) |
|||
{ |
|||
moduleExtensionDto.Configuration[customConfig.Key] = customConfig.Value; |
|||
} |
|||
|
|||
return moduleExtensionDto; |
|||
} |
|||
|
|||
protected virtual EntityExtensionDto GetEntityExtensionDto( |
|||
EntityExtensionConfiguration entityConfig) |
|||
{ |
|||
var entityExtensionDto = new EntityExtensionDto |
|||
{ |
|||
Properties = new Dictionary<string, ExtensionPropertyDto>(), |
|||
Configuration = new Dictionary<string, object>() |
|||
}; |
|||
|
|||
foreach (var propertyConfig in entityConfig.GetProperties()) |
|||
{ |
|||
if (!propertyConfig.IsAvailableToClients) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
entityExtensionDto.Properties[propertyConfig.Name] = CreateExtensionPropertyDto(propertyConfig); |
|||
} |
|||
|
|||
foreach (var customConfig in entityConfig.Configuration.Where(c => !c.Key.StartsWith("_"))) |
|||
{ |
|||
entityExtensionDto.Configuration[customConfig.Key] = customConfig.Value; |
|||
} |
|||
|
|||
return entityExtensionDto; |
|||
} |
|||
|
|||
protected virtual ExtensionPropertyDto CreateExtensionPropertyDto( |
|||
ExtensionPropertyConfiguration propertyConfig) |
|||
{ |
|||
var extensionPropertyDto = new ExtensionPropertyDto |
|||
{ |
|||
Type = TypeHelper.GetFullNameHandlingNullableAndGenerics(propertyConfig.Type), |
|||
TypeSimple = TypeHelper.GetSimplifiedName(propertyConfig.Type), |
|||
Attributes = new List<ExtensionPropertyAttributeDto>(), |
|||
DisplayName = CreateDisplayNameDto(propertyConfig), |
|||
Configuration = new Dictionary<string, object>(), |
|||
Api = new ExtensionPropertyApiDto |
|||
{ |
|||
OnGet = new ExtensionPropertyApiGetDto |
|||
{ |
|||
IsAvailable = propertyConfig.Api.OnGet.IsAvailable |
|||
}, |
|||
OnCreate = new ExtensionPropertyApiCreateDto |
|||
{ |
|||
IsAvailable = propertyConfig.Api.OnCreate.IsAvailable |
|||
}, |
|||
OnUpdate = new ExtensionPropertyApiUpdateDto |
|||
{ |
|||
IsAvailable = propertyConfig.Api.OnUpdate.IsAvailable |
|||
} |
|||
}, |
|||
Ui = new ExtensionPropertyUiDto |
|||
{ |
|||
OnCreateForm = new ExtensionPropertyUiFormDto |
|||
{ |
|||
IsVisible = propertyConfig.UI.OnCreateForm.IsVisible |
|||
}, |
|||
OnEditForm = new ExtensionPropertyUiFormDto |
|||
{ |
|||
IsVisible = propertyConfig.UI.OnEditForm.IsVisible |
|||
}, |
|||
OnTable = new ExtensionPropertyUiTableDto |
|||
{ |
|||
IsVisible = propertyConfig.UI.OnTable.IsVisible |
|||
} |
|||
} |
|||
}; |
|||
|
|||
foreach (var attribute in propertyConfig.Attributes) |
|||
{ |
|||
extensionPropertyDto.Attributes.Add( |
|||
ExtensionPropertyAttributeDto.Create(attribute) |
|||
); |
|||
} |
|||
|
|||
foreach (var customConfig in propertyConfig.Configuration.Where(c => !c.Key.StartsWith("_"))) |
|||
{ |
|||
extensionPropertyDto.Configuration[customConfig.Key] = customConfig.Value; |
|||
} |
|||
|
|||
return extensionPropertyDto; |
|||
} |
|||
|
|||
protected virtual LocalizableStringDto CreateDisplayNameDto(ExtensionPropertyConfiguration propertyConfig) |
|||
{ |
|||
if (propertyConfig.DisplayName == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
if (propertyConfig.DisplayName is LocalizableString localizableStringInstance) |
|||
{ |
|||
return new LocalizableStringDto( |
|||
localizableStringInstance.Name, |
|||
localizableStringInstance.ResourceType != null |
|||
? LocalizationResourceNameAttribute.GetName(localizableStringInstance.ResourceType) |
|||
: null |
|||
); |
|||
} |
|||
|
|||
if (propertyConfig.DisplayName is FixedLocalizableString fixedLocalizableString) |
|||
{ |
|||
// "_" means don't use the default resource, but directly use the name.
|
|||
return new LocalizableStringDto(fixedLocalizableString.Value, "_"); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
[Serializable] |
|||
public class EntityExtensionDto |
|||
{ |
|||
public Dictionary<string, ExtensionPropertyDto> Properties { get; set; } |
|||
|
|||
public Dictionary<string, object> Configuration { get; set; } |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
[Serializable] |
|||
public class ExtensionPropertyApiCreateDto |
|||
{ |
|||
/// <summary>
|
|||
/// Default: true.
|
|||
/// </summary>
|
|||
public bool IsAvailable { get; set; } = true; |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
public class ExtensionPropertyApiDto |
|||
{ |
|||
[NotNull] |
|||
public ExtensionPropertyApiGetDto OnGet { get; set; } |
|||
|
|||
[NotNull] |
|||
public ExtensionPropertyApiCreateDto OnCreate { get; set; } |
|||
|
|||
[NotNull] |
|||
public ExtensionPropertyApiUpdateDto OnUpdate { get; set; } |
|||
|
|||
public ExtensionPropertyApiDto() |
|||
{ |
|||
OnGet = new ExtensionPropertyApiGetDto(); |
|||
OnCreate = new ExtensionPropertyApiCreateDto(); |
|||
OnUpdate = new ExtensionPropertyApiUpdateDto(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
[Serializable] |
|||
public class ExtensionPropertyApiGetDto |
|||
{ |
|||
/// <summary>
|
|||
/// Default: true.
|
|||
/// </summary>
|
|||
public bool IsAvailable { get; set; } = true; |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
[Serializable] |
|||
public class ExtensionPropertyApiUpdateDto |
|||
{ |
|||
/// <summary>
|
|||
/// Default: true.
|
|||
/// </summary>
|
|||
public bool IsAvailable { get; set; } = true; |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Reflection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
[Serializable] |
|||
public class ExtensionPropertyAttributeDto |
|||
{ |
|||
public string Type { get; set; } |
|||
public string TypeSimple { get; set; } |
|||
public Dictionary<string, object> Configuration { get; set; } |
|||
|
|||
public static ExtensionPropertyAttributeDto Create(Attribute attribute) |
|||
{ |
|||
var attributeType = attribute.GetType(); |
|||
var dto = new ExtensionPropertyAttributeDto |
|||
{ |
|||
Type = TypeHelper.GetFullNameHandlingNullableAndGenerics(attributeType), |
|||
TypeSimple = TypeHelper.GetSimplifiedName(attributeType), |
|||
Configuration = new Dictionary<string, object>() |
|||
}; |
|||
|
|||
if (attribute is StringLengthAttribute stringLengthAttribute) |
|||
{ |
|||
dto.Configuration["MaximumLength"] = stringLengthAttribute.MaximumLength; |
|||
dto.Configuration["MinimumLength"] = stringLengthAttribute.MinimumLength; |
|||
} |
|||
|
|||
//TODO: Others!
|
|||
|
|||
return dto; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
[Serializable] |
|||
public class ExtensionPropertyDto |
|||
{ |
|||
public string Type { get; set; } |
|||
|
|||
public string TypeSimple { get; set; } |
|||
|
|||
[CanBeNull] |
|||
public LocalizableStringDto DisplayName { get; set; } |
|||
|
|||
public ExtensionPropertyApiDto Api { get; set; } |
|||
|
|||
public ExtensionPropertyUiDto Ui { get; set; } |
|||
|
|||
public List<ExtensionPropertyAttributeDto> Attributes { get; set; } |
|||
|
|||
public Dictionary<string, object> Configuration { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
[Serializable] |
|||
public class ExtensionPropertyUiDto |
|||
{ |
|||
public ExtensionPropertyUiTableDto OnTable { get; set; } |
|||
public ExtensionPropertyUiFormDto OnCreateForm { get; set; } |
|||
public ExtensionPropertyUiFormDto OnEditForm { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
[Serializable] |
|||
public class ExtensionPropertyUiFormDto |
|||
{ |
|||
public bool IsVisible { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
[Serializable] |
|||
public class ExtensionPropertyUiTableDto |
|||
{ |
|||
public bool IsVisible { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
public interface ICachedObjectExtensionsDtoService |
|||
{ |
|||
ObjectExtensionsDto Get(); |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using System; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
[Serializable] |
|||
public class LocalizableStringDto |
|||
{ |
|||
[NotNull] |
|||
public string Name { get; private set; } |
|||
|
|||
[CanBeNull] |
|||
public string Resource { get; set; } |
|||
|
|||
public LocalizableStringDto([NotNull] string name, string resource = null) |
|||
{ |
|||
Name = Check.NotNullOrEmpty(name, nameof(name)); |
|||
Resource = resource; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
[Serializable] |
|||
public class ModuleExtensionDto |
|||
{ |
|||
public Dictionary<string, EntityExtensionDto> Entities { get; set; } |
|||
|
|||
public Dictionary<string, object> Configuration { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending |
|||
{ |
|||
[Serializable] |
|||
public class ObjectExtensionsDto |
|||
{ |
|||
public Dictionary<string, ModuleExtensionDto> Modules { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars |
|||
{ |
|||
public class AbpPageToolbarOptions |
|||
{ |
|||
public PageToolbarDictionary Toolbars { get; } |
|||
|
|||
public AbpPageToolbarOptions() |
|||
{ |
|||
Toolbars = new PageToolbarDictionary(); |
|||
} |
|||
|
|||
public void Configure<TPage>([NotNull] Action<PageToolbar> configureAction) |
|||
{ |
|||
// ReSharper disable once AssignNullToNotNullAttribute
|
|||
Configure(typeof(TPage).FullName, configureAction); |
|||
} |
|||
|
|||
public void Configure([NotNull]string pageName, [NotNull]Action<PageToolbar> configureAction) |
|||
{ |
|||
Check.NotNullOrWhiteSpace(pageName, nameof(pageName)); |
|||
Check.NotNull(configureAction, nameof(configureAction)); |
|||
|
|||
var toolbar = Toolbars.GetOrAdd(pageName, () => new PageToolbar(pageName)); |
|||
configureAction(toolbar); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars |
|||
{ |
|||
public interface IPageToolbarContributor |
|||
{ |
|||
Task ContributeAsync(PageToolbarContributionContext context); |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars |
|||
{ |
|||
public interface IPageToolbarManager |
|||
{ |
|||
Task<PageToolbarItem[]> GetItemsAsync(string pageName); |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars |
|||
{ |
|||
public class PageToolbar |
|||
{ |
|||
public string PageName { get; } |
|||
|
|||
public PageToolbarContributorList Contributors { get; set; } |
|||
|
|||
public PageToolbar([NotNull] string pageName) |
|||
{ |
|||
PageName = Check.NotNullOrEmpty(pageName, nameof(pageName)); |
|||
Contributors = new PageToolbarContributorList(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
using System; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars |
|||
{ |
|||
public class PageToolbarContributionContext |
|||
{ |
|||
[NotNull] |
|||
public string PageName { get; } |
|||
|
|||
[NotNull] |
|||
public IServiceProvider ServiceProvider { get; } |
|||
|
|||
[NotNull] |
|||
public PageToolbarItemList Items { get; } |
|||
|
|||
public PageToolbarContributionContext( |
|||
[NotNull] string pageName, |
|||
[NotNull] IServiceProvider serviceProvider) |
|||
{ |
|||
PageName = Check.NotNull(pageName, nameof(pageName)); |
|||
ServiceProvider = Check.NotNull(serviceProvider, nameof(serviceProvider)); |
|||
|
|||
Items = new PageToolbarItemList(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars |
|||
{ |
|||
public abstract class PageToolbarContributor : IPageToolbarContributor |
|||
{ |
|||
public abstract Task ContributeAsync(PageToolbarContributionContext context); |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars |
|||
{ |
|||
public class PageToolbarContributorList : List<IPageToolbarContributor> |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars |
|||
{ |
|||
public class PageToolbarDictionary : Dictionary<string, PageToolbar> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,84 @@ |
|||
using System; |
|||
using Localization.Resources.AbpUi; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar.Button; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars |
|||
{ |
|||
public static class PageToolbarExtensions |
|||
{ |
|||
public static PageToolbar AddComponent<TComponent>( |
|||
this PageToolbar toolbar, |
|||
object argument = null, |
|||
int order = 0, |
|||
string requiredPolicyName = null) |
|||
{ |
|||
return toolbar.AddComponent( |
|||
typeof(TComponent), |
|||
argument, |
|||
order, |
|||
requiredPolicyName |
|||
); |
|||
} |
|||
|
|||
public static PageToolbar AddComponent( |
|||
this PageToolbar toolbar, |
|||
Type componentType, |
|||
object argument = null, |
|||
int order = 0, |
|||
string requiredPolicyName = null) |
|||
{ |
|||
toolbar.Contributors.Add( |
|||
new SimplePageToolbarContributor( |
|||
componentType, |
|||
argument, |
|||
order, |
|||
requiredPolicyName |
|||
) |
|||
); |
|||
|
|||
return toolbar; |
|||
} |
|||
|
|||
public static PageToolbar AddButton( |
|||
this PageToolbar toolbar, |
|||
ILocalizableString text, |
|||
string icon = null, |
|||
string name = null, |
|||
string id = null, |
|||
ILocalizableString busyText = null, |
|||
FontIconType iconType = FontIconType.FontAwesome, |
|||
AbpButtonType type = AbpButtonType.Primary, |
|||
AbpButtonSize size = AbpButtonSize.Small, |
|||
bool disabled = false, |
|||
int order = 0, |
|||
string requiredPolicyName = null) |
|||
{ |
|||
if (busyText == null) |
|||
{ |
|||
busyText = new LocalizableString(typeof(AbpUiResource), "ProcessingWithThreeDot"); |
|||
} |
|||
|
|||
toolbar.AddComponent<AbpPageToolbarButtonViewComponent>( |
|||
new |
|||
{ |
|||
text, |
|||
icon, |
|||
name, |
|||
id, |
|||
busyText, |
|||
iconType, |
|||
type, |
|||
size, |
|||
disabled |
|||
}, |
|||
order, |
|||
requiredPolicyName |
|||
); |
|||
|
|||
return toolbar; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
using System; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars |
|||
{ |
|||
public class PageToolbarItem |
|||
{ |
|||
[NotNull] |
|||
public Type ComponentType { get; } |
|||
|
|||
[CanBeNull] |
|||
public object Arguments { get; set; } |
|||
|
|||
public int Order { get; set; } |
|||
|
|||
public PageToolbarItem( |
|||
[NotNull] Type componentType, |
|||
[CanBeNull] 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.Mvc.UI.Theme.Shared.PageToolbars |
|||
{ |
|||
public class PageToolbarItemList : List<PageToolbarItem> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars |
|||
{ |
|||
public class PageToolbarManager : IPageToolbarManager, ITransientDependency |
|||
{ |
|||
protected AbpPageToolbarOptions Options { get; } |
|||
protected IHybridServiceScopeFactory ServiceScopeFactory { get; } |
|||
|
|||
public PageToolbarManager( |
|||
IOptions<AbpPageToolbarOptions> options, |
|||
IHybridServiceScopeFactory serviceScopeFactory) |
|||
{ |
|||
Options = options.Value; |
|||
ServiceScopeFactory = serviceScopeFactory; |
|||
} |
|||
|
|||
public virtual async Task<PageToolbarItem[]> GetItemsAsync(string pageName) |
|||
{ |
|||
var toolbar = Options.Toolbars.GetOrDefault(pageName); |
|||
if (toolbar == null || !toolbar.Contributors.Any()) |
|||
{ |
|||
return Array.Empty<PageToolbarItem>(); |
|||
} |
|||
|
|||
using (var scope = ServiceScopeFactory.CreateScope()) |
|||
{ |
|||
var context = new PageToolbarContributionContext(pageName, scope.ServiceProvider); |
|||
|
|||
foreach (var contributor in toolbar.Contributors) |
|||
{ |
|||
await contributor.ContributeAsync(context); |
|||
} |
|||
|
|||
return context.Items.OrderBy(i => i.Order).ToArray(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars |
|||
{ |
|||
public class SimplePageToolbarContributor : IPageToolbarContributor |
|||
{ |
|||
public Type ComponentType { get; } |
|||
|
|||
public object Argument { get; set; } |
|||
|
|||
public int Order { get; } |
|||
|
|||
public string RequiredPolicyName { get; } |
|||
|
|||
public SimplePageToolbarContributor( |
|||
Type componentType, |
|||
object argument = null, |
|||
int order = 0, |
|||
string requiredPolicyName = null) |
|||
{ |
|||
ComponentType = componentType; |
|||
Argument = argument; |
|||
Order = order; |
|||
RequiredPolicyName = requiredPolicyName; |
|||
} |
|||
|
|||
public async Task ContributeAsync(PageToolbarContributionContext context) |
|||
{ |
|||
if(await ShouldAddComponentAsync(context)) |
|||
{ |
|||
context.Items.Add(new PageToolbarItem(ComponentType, Argument, 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,22 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar |
|||
{ |
|||
public class AbpPageToolbarViewComponent : AbpViewComponent |
|||
{ |
|||
private readonly IPageToolbarManager _toolbarManager; |
|||
|
|||
public AbpPageToolbarViewComponent(IPageToolbarManager toolbarManager) |
|||
{ |
|||
_toolbarManager = toolbarManager; |
|||
} |
|||
|
|||
public async Task<IViewComponentResult> InvokeAsync(string pageName) |
|||
{ |
|||
var items = await _toolbarManager.GetItemsAsync(pageName); |
|||
return View("~/Pages/Shared/Components/AbpPageToolbar/Default.cshtml", items); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.Extensions.Localization; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar.Button |
|||
{ |
|||
public class AbpPageToolbarButtonViewComponent : AbpViewComponent |
|||
{ |
|||
protected IStringLocalizerFactory StringLocalizerFactory { get; } |
|||
|
|||
public AbpPageToolbarButtonViewComponent(IStringLocalizerFactory stringLocalizerFactory) |
|||
{ |
|||
StringLocalizerFactory = stringLocalizerFactory; |
|||
} |
|||
|
|||
public IViewComponentResult Invoke( |
|||
ILocalizableString text, |
|||
string name, |
|||
string icon, |
|||
string id, |
|||
ILocalizableString busyText, |
|||
FontIconType iconType, |
|||
AbpButtonType type, |
|||
AbpButtonSize size, |
|||
bool disabled) |
|||
{ |
|||
Check.NotNull(text, nameof(text)); |
|||
|
|||
return View( |
|||
"~/Pages/Shared/Components/AbpPageToolbar/Button/Default.cshtml", |
|||
new AbpPageToolbarButtonViewModel( |
|||
text.Localize(StringLocalizerFactory), |
|||
name, |
|||
icon, |
|||
id, |
|||
busyText?.Localize(StringLocalizerFactory), |
|||
iconType, |
|||
type, |
|||
size, |
|||
disabled |
|||
) |
|||
); |
|||
} |
|||
|
|||
public class AbpPageToolbarButtonViewModel |
|||
{ |
|||
public string Text { get; } |
|||
public string Name { get; } |
|||
public string Icon { get; } |
|||
public string Id { get; } |
|||
public string BusyText { get; } |
|||
public FontIconType IconType { get; } |
|||
public AbpButtonType Type { get; } |
|||
public AbpButtonSize Size { get; } |
|||
public bool Disabled { get; } |
|||
|
|||
public AbpPageToolbarButtonViewModel( |
|||
string text, |
|||
string name, |
|||
string icon, |
|||
string id, |
|||
string busyText, |
|||
FontIconType iconType, |
|||
AbpButtonType type, |
|||
AbpButtonSize size, |
|||
bool disabled) |
|||
{ |
|||
Text = text; |
|||
Name = name; |
|||
Icon = icon; |
|||
Id = id; |
|||
BusyText = busyText; |
|||
IconType = iconType; |
|||
Type = type; |
|||
Size = size; |
|||
Disabled = disabled; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
@model Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPageToolbar.Button.AbpPageToolbarButtonViewComponent.AbpPageToolbarButtonViewModel |
|||
<abp-button |
|||
text="@Model.Text" |
|||
name="@Model.Name" |
|||
icon="@Model.Icon" |
|||
id="@Model.Id" |
|||
busy-text="@Model.BusyText" |
|||
icon-type="@Model.IconType" |
|||
button-type="@Model.Type" |
|||
size="@Model.Size" |
|||
disabled="@Model.Disabled" |
|||
class="mx-1" |
|||
/> |
|||
@ -0,0 +1,5 @@ |
|||
@model Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.PageToolbars.PageToolbarItem[] |
|||
@foreach (var toolbarItem in Model) |
|||
{ |
|||
@(await Component.InvokeAsync(toolbarItem.ComponentType, toolbarItem.Arguments)) |
|||
} |
|||
@ -0,0 +1,4 @@ |
|||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers |
|||
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI |
|||
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap |
|||
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling |
|||
@ -0,0 +1,192 @@ |
|||
var abp = abp || {}; |
|||
(function () { |
|||
abp.ui = abp.ui || {}; |
|||
abp.ui.extensions = abp.ui.extensions || {}; |
|||
|
|||
abp.ui.extensions.ActionList = function () { |
|||
return new abp.utils.common.LinkedList(); |
|||
}; |
|||
|
|||
abp.ui.extensions.ColumnList = function () { |
|||
return new abp.utils.common.LinkedList(); |
|||
}; |
|||
|
|||
abp.ui.extensions.entityActions = (function () { |
|||
var _callbackLists = {}; |
|||
|
|||
function _get(name) { |
|||
var callbackList = _callbackLists[name]; |
|||
|
|||
if (!callbackList) { |
|||
callbackList = _callbackLists[name] = []; |
|||
} |
|||
|
|||
return { |
|||
addContributor: _addContributor, |
|||
get actions() { |
|||
return _getActions(); |
|||
} |
|||
}; |
|||
|
|||
function _addContributor(contributeCallback, order) { |
|||
if (order === undefined || order >= callbackList.length) { |
|||
callbackList.push(contributeCallback); |
|||
} else if (order === 0) { |
|||
callbackList.unshift(contributeCallback); |
|||
} else { |
|||
callbackList.splice(order, 0, contributeCallback); |
|||
} |
|||
} |
|||
|
|||
function _getActions() { |
|||
var actionList = new abp.ui.extensions.ActionList(); |
|||
|
|||
callbackList.forEach(function (callback) { |
|||
callback(actionList); |
|||
}); |
|||
|
|||
return actionList; |
|||
} |
|||
} |
|||
|
|||
return { |
|||
get: _get |
|||
}; |
|||
})(); |
|||
|
|||
abp.ui.extensions.tableColumns = (function () { |
|||
var _callbackLists = {}; |
|||
|
|||
function _get(name) { |
|||
var callbackList = _callbackLists[name]; |
|||
|
|||
if (!callbackList) { |
|||
callbackList = _callbackLists[name] = []; |
|||
} |
|||
|
|||
return { |
|||
addContributor: _addContributor, |
|||
get columns() { |
|||
return _getColumns(); |
|||
} |
|||
}; |
|||
|
|||
function _addContributor(contributeCallback, order) { |
|||
if (order === undefined || order >= callbackList.length) { |
|||
callbackList.push(contributeCallback); |
|||
} else if (order === 0) { |
|||
callbackList.unshift(contributeCallback); |
|||
} else { |
|||
callbackList.splice(order, 0, contributeCallback); |
|||
} |
|||
} |
|||
|
|||
function _getColumns() { |
|||
var columnList = new abp.ui.extensions.ColumnList(); |
|||
|
|||
callbackList.forEach(function (callback) { |
|||
callback(columnList); |
|||
}); |
|||
|
|||
return columnList; |
|||
} |
|||
} |
|||
|
|||
return { |
|||
get: _get |
|||
}; |
|||
})(); |
|||
|
|||
function initializeObjectExtensions() { |
|||
|
|||
function localizeDisplayName(propertyName, displayName) { |
|||
if (displayName && displayName.name) { |
|||
return abp.localization.localize(displayName.name, displayName.resource); |
|||
} |
|||
|
|||
if (abp.localization.isLocalized('DisplayName:' + propertyName)) { |
|||
return abp.localization.localize('DisplayName:' + propertyName); |
|||
} |
|||
|
|||
return abp.localization.localize(propertyName); |
|||
} |
|||
|
|||
function configureTableColumns(tableName, columnConfigs) { |
|||
abp.ui.extensions.tableColumns.get(tableName) |
|||
.addContributor( |
|||
function (columnList) { |
|||
columnList.addManyTail(columnConfigs); |
|||
} |
|||
); |
|||
} |
|||
|
|||
function getTableProperties(objectConfig) { |
|||
var propertyNames = Object.keys(objectConfig.properties); |
|||
var tableProperties = []; |
|||
for (var i = 0; i < propertyNames.length; i++) { |
|||
var propertyName = propertyNames[i]; |
|||
var propertyConfig = objectConfig.properties[propertyName]; |
|||
if (propertyConfig.ui.onTable.isVisible) { |
|||
tableProperties.push({ |
|||
name: propertyName, |
|||
config: propertyConfig |
|||
}); |
|||
} |
|||
} |
|||
|
|||
return tableProperties; |
|||
} |
|||
|
|||
function convertPropertiesToColumnConfigs(properties) { |
|||
var columnConfigs = []; |
|||
|
|||
for (var i = 0; i < properties.length; i++) { |
|||
var tableProperty = properties[i]; |
|||
columnConfigs.push({ |
|||
title: localizeDisplayName(tableProperty.name, tableProperty.config.displayName), |
|||
data: "extraProperties." + tableProperty.name |
|||
}); |
|||
} |
|||
|
|||
return columnConfigs; |
|||
} |
|||
|
|||
function configureEntity(moduleName, entityName, entityConfig) { |
|||
var tableProperties = getTableProperties(entityConfig); |
|||
|
|||
if (tableProperties.length > 0) { |
|||
var tableName = abp.utils.toCamelCase(moduleName) + "." + abp.utils.toCamelCase(entityName); |
|||
var columnConfigs = convertPropertiesToColumnConfigs(tableProperties); |
|||
configureTableColumns( |
|||
tableName, |
|||
columnConfigs |
|||
); |
|||
} |
|||
} |
|||
|
|||
function configureModule(moduleName, moduleConfig) { |
|||
var entityNames = Object.keys(moduleConfig.entities); |
|||
for (var i = 0; i < entityNames.length; i++) { |
|||
configureEntity( |
|||
moduleName, |
|||
entityNames[i], |
|||
moduleConfig.entities[entityNames[i]] |
|||
); |
|||
} |
|||
} |
|||
|
|||
var moduleNames = Object.keys(abp.objectExtensions.modules); |
|||
|
|||
for (var i = 0; i < moduleNames.length; i++) { |
|||
configureModule( |
|||
moduleNames[i], |
|||
abp.objectExtensions.modules[moduleNames[i]] |
|||
); |
|||
} |
|||
} |
|||
|
|||
abp.event.on('abp.configurationInitialized', function () { |
|||
initializeObjectExtensions(); |
|||
}); |
|||
|
|||
})(); |
|||
@ -1,26 +0,0 @@ |
|||
using System; |
|||
using System.Globalization; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Localization |
|||
{ |
|||
internal static class GlobalizationHelper |
|||
{ |
|||
public static bool IsValidCultureCode(string cultureCode) |
|||
{ |
|||
if (cultureCode.IsNullOrWhiteSpace()) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
CultureInfo.GetCultureInfo(cultureCode); |
|||
return true; |
|||
} |
|||
catch (CultureNotFoundException) |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Data; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ModelBinding |
|||
{ |
|||
public class AbpExtraPropertiesDictionaryModelBinderProvider : IModelBinderProvider |
|||
{ |
|||
public IModelBinder GetBinder(ModelBinderProviderContext context) |
|||
{ |
|||
if (context == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(context)); |
|||
} |
|||
|
|||
if (context.Metadata.ModelType != typeof(Dictionary<string, object>)) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
if (!context.Metadata.ContainerType.IsAssignableTo<IHasExtraProperties>()) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var binderType = typeof(DictionaryModelBinder<string, object>); |
|||
var keyBinder = context.CreateBinder(context.MetadataProvider.GetMetadataForType(typeof(string))); |
|||
var valueBinder = new AbpExtraPropertyModelBinder(context.Metadata.ContainerType); |
|||
var loggerFactory = context.Services.GetRequiredService<ILoggerFactory>(); |
|||
var mvcOptions = context.Services.GetRequiredService<IOptions<MvcOptions>>().Value; |
|||
|
|||
return (IModelBinder)Activator.CreateInstance( |
|||
binderType, |
|||
keyBinder, |
|||
valueBinder, |
|||
loggerFactory, |
|||
true /* allowValidatingTopLevelNodes */, |
|||
mvcOptions); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding; |
|||
using Volo.Abp.ObjectExtending; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ModelBinding |
|||
{ |
|||
public class AbpExtraPropertyModelBinder : IModelBinder |
|||
{ |
|||
public Type ExtensibleObjectType { get; } |
|||
|
|||
public AbpExtraPropertyModelBinder(Type extensibleObjectType) |
|||
{ |
|||
ExtensibleObjectType = extensibleObjectType; |
|||
} |
|||
|
|||
public virtual Task BindModelAsync(ModelBindingContext bindingContext) |
|||
{ |
|||
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); |
|||
if (valueProviderResult == ValueProviderResult.None) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult); |
|||
|
|||
var model = ConvertStringToPropertyType( |
|||
bindingContext, |
|||
valueProviderResult.FirstValue |
|||
); |
|||
|
|||
bindingContext.Result = ModelBindingResult.Success(model); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual object ConvertStringToPropertyType(ModelBindingContext bindingContext, string value) |
|||
{ |
|||
if (bindingContext.ModelMetadata.ConvertEmptyStringToNull && string.IsNullOrWhiteSpace(value)) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var extensionInfo = ObjectExtensionManager.Instance.GetOrNull(ExtensibleObjectType); |
|||
if (extensionInfo == null) |
|||
{ |
|||
return value; |
|||
} |
|||
|
|||
var propertyName = ExtraPropertyBindingHelper.ExtractExtraPropertyName(bindingContext.ModelName); |
|||
if (propertyName == null) |
|||
{ |
|||
return value; |
|||
} |
|||
|
|||
var propertyInfo = extensionInfo.GetPropertyOrNull(propertyName); |
|||
if (propertyInfo == null) |
|||
{ |
|||
return value; |
|||
} |
|||
|
|||
return Convert.ChangeType(value, propertyInfo.Type); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ModelBinding |
|||
{ |
|||
public static class ExtraPropertyBindingHelper |
|||
{ |
|||
/// <summary>
|
|||
/// <paramref name="expression"/> is a string like "UserInfo.ExtraProperties[SocialSecurityNumber]"
|
|||
/// This method returns "SocialSecurityNumber" for this example. */
|
|||
/// </summary>
|
|||
public static string ExtractExtraPropertyName(string expression) |
|||
{ |
|||
var index = expression.IndexOf("ExtraProperties[", StringComparison.Ordinal); |
|||
if (index < 0) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return expression.Substring(index + 16, expression.Length - index - 17); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// <paramref name="expression"/> is a string like "UserInfo.ExtraProperties[SocialSecurityNumber]"
|
|||
/// This method returns "UserInfo" for this example.
|
|||
/// </summary>
|
|||
public static string ExtractContainerName(string expression) |
|||
{ |
|||
var index = expression.IndexOf("ExtraProperties[", StringComparison.Ordinal); |
|||
if (index < 0) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return expression.Left(index).TrimEnd('.'); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using System.Reflection; |
|||
using System.Text; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Validation |
|||
{ |
|||
public static class ValidationAttributeHelper |
|||
{ |
|||
private static readonly PropertyInfo ValidationAttributeErrorMessageStringProperty = typeof(ValidationAttribute) |
|||
.GetProperty("ErrorMessageString", BindingFlags.Instance | BindingFlags.NonPublic); |
|||
|
|||
public static void SetDefaultErrorMessage(ValidationAttribute validationAttribute) |
|||
{ |
|||
validationAttribute.ErrorMessage = |
|||
ValidationAttributeErrorMessageStringProperty.GetValue(validationAttribute) as string; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,132 @@ |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using System.Reflection; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.DataAnnotations; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; |
|||
using Microsoft.AspNetCore.Mvc.Rendering; |
|||
using Microsoft.AspNetCore.Mvc.ViewFeatures; |
|||
using Microsoft.Extensions.Localization; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.AspNetCore.Mvc.ModelBinding; |
|||
using Volo.Abp.AspNetCore.Mvc.Validation; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.ObjectExtending; |
|||
using Volo.Abp.Validation.Localization; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ViewFeatures |
|||
{ |
|||
[Dependency(ReplaceServices = true)] |
|||
[ExposeServices(typeof(ValidationHtmlAttributeProvider))] |
|||
public class AbpValidationHtmlAttributeProvider |
|||
: DefaultValidationHtmlAttributeProvider, ISingletonDependency |
|||
{ |
|||
private readonly IModelMetadataProvider _metadataProvider; |
|||
private readonly IStringLocalizerFactory _stringLocalizerFactory; |
|||
private readonly IStringLocalizer<AbpValidationResource> _validationStringLocalizer; |
|||
private readonly IValidationAttributeAdapterProvider _validationAttributeAdapterProvider; |
|||
|
|||
public AbpValidationHtmlAttributeProvider( |
|||
IOptions<MvcViewOptions> optionsAccessor, |
|||
IModelMetadataProvider metadataProvider, |
|||
ClientValidatorCache clientValidatorCache, |
|||
IValidationAttributeAdapterProvider validationAttributeAdapterProvider, |
|||
IStringLocalizerFactory stringLocalizerFactory, |
|||
IStringLocalizer<AbpValidationResource> validationStringLocalizer) |
|||
: base( |
|||
optionsAccessor, |
|||
metadataProvider, |
|||
clientValidatorCache) |
|||
{ |
|||
_metadataProvider = metadataProvider; |
|||
_validationAttributeAdapterProvider = validationAttributeAdapterProvider; |
|||
_stringLocalizerFactory = stringLocalizerFactory; |
|||
_validationStringLocalizer = validationStringLocalizer; |
|||
} |
|||
|
|||
public override void AddValidationAttributes( |
|||
ViewContext viewContext, |
|||
ModelExplorer modelExplorer, |
|||
IDictionary<string, string> attributes) |
|||
{ |
|||
base.AddValidationAttributes(viewContext, modelExplorer, attributes); |
|||
AddExtraPropertyValidationsAttributes(viewContext, modelExplorer, attributes); |
|||
} |
|||
|
|||
protected virtual void AddExtraPropertyValidationsAttributes(ViewContext viewContext, ModelExplorer modelExplorer, IDictionary<string, string> attributes) |
|||
{ |
|||
var nameAttribute = attributes.GetOrDefault("name"); |
|||
if (nameAttribute == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var extraPropertyName = ExtraPropertyBindingHelper.ExtractExtraPropertyName(nameAttribute); |
|||
if (extraPropertyName == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
//TODO: containerName can be null on controller actions..?
|
|||
var containerName = ExtraPropertyBindingHelper.ExtractContainerName(nameAttribute); |
|||
if (containerName == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (modelExplorer.Container?.ModelType == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var extensibleObjectType = modelExplorer.Container.ModelType |
|||
.GetProperty(containerName, BindingFlags.Instance | BindingFlags.Public) |
|||
?.PropertyType; |
|||
if (extensibleObjectType == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var extensionPropertyInfo = ObjectExtensionManager.Instance.GetPropertyOrNull( |
|||
extensibleObjectType, |
|||
extraPropertyName |
|||
); |
|||
|
|||
if (extensionPropertyInfo == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (modelExplorer.Metadata is DefaultModelMetadata metadata) |
|||
{ |
|||
metadata.DisplayMetadata.DisplayName = |
|||
() => extensionPropertyInfo.GetLocalizedDisplayName(_stringLocalizerFactory); |
|||
} |
|||
|
|||
foreach (var validationAttribute in extensionPropertyInfo.GetValidationAttributes()) |
|||
{ |
|||
var validationContext = new ClientModelValidationContext( |
|||
viewContext, |
|||
modelExplorer.Metadata, |
|||
_metadataProvider, |
|||
attributes |
|||
); |
|||
|
|||
if (validationAttribute.ErrorMessage == null) |
|||
{ |
|||
ValidationAttributeHelper.SetDefaultErrorMessage(validationAttribute); |
|||
} |
|||
|
|||
var validationAttributeAdapter = _validationAttributeAdapterProvider.GetAttributeAdapter( |
|||
validationAttribute, |
|||
_validationStringLocalizer |
|||
); |
|||
|
|||
validationAttributeAdapter?.AddValidation(validationContext); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
using System; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
|
|||
namespace Volo.Abp.ObjectExtending |
|||
{ |
|||
public static class ObjectExtensionPropertyInfoAspNetCoreMvcExtensions |
|||
{ |
|||
public static string GetInputType(this ObjectExtensionPropertyInfo propertyInfo) |
|||
{ |
|||
foreach (var attribute in propertyInfo.Attributes) |
|||
{ |
|||
var inputTypeByAttribute = GetInputTypeFromAttributeOrNull(attribute); |
|||
if (inputTypeByAttribute != null) |
|||
{ |
|||
return inputTypeByAttribute; |
|||
} |
|||
} |
|||
|
|||
return GetInputTypeFromTypeOrNull(propertyInfo.Type) |
|||
?? "text"; //default
|
|||
} |
|||
|
|||
private static string GetInputTypeFromAttributeOrNull(Attribute attribute) |
|||
{ |
|||
if (attribute is EmailAddressAttribute) |
|||
{ |
|||
return "email"; |
|||
} |
|||
|
|||
if (attribute is UrlAttribute) |
|||
{ |
|||
return "url"; |
|||
} |
|||
|
|||
if (attribute is HiddenInputAttribute) |
|||
{ |
|||
return "hidden"; |
|||
} |
|||
|
|||
if (attribute is PhoneAttribute) |
|||
{ |
|||
return "tel"; |
|||
} |
|||
|
|||
if (attribute is DataTypeAttribute dataTypeAttribute) |
|||
{ |
|||
switch (dataTypeAttribute.DataType) |
|||
{ |
|||
case DataType.Password: |
|||
return "password"; |
|||
case DataType.Date: |
|||
return "date"; |
|||
case DataType.Time: |
|||
return "time"; |
|||
case DataType.EmailAddress: |
|||
return "email"; |
|||
case DataType.Url: |
|||
return "url"; |
|||
case DataType.PhoneNumber: |
|||
return "tel"; |
|||
case DataType.DateTime: |
|||
return "datetime-local"; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
private static string GetInputTypeFromTypeOrNull(Type type) |
|||
{ |
|||
if (type == typeof(bool)) |
|||
{ |
|||
return "checkbox"; |
|||
} |
|||
|
|||
if (type == typeof(DateTime)) |
|||
{ |
|||
return "datetime-local"; |
|||
} |
|||
|
|||
if (type == typeof(int) || |
|||
type == typeof(long) || |
|||
type == typeof(byte) || |
|||
type == typeof(sbyte) || |
|||
type == typeof(short) || |
|||
type == typeof(ushort) || |
|||
type == typeof(uint) || |
|||
type == typeof(long) || |
|||
type == typeof(ulong)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
{ |
|||
"culture": "tr", |
|||
"texts": { |
|||
"DisplayName:Abp.Mailing.DefaultFromAddress": "Varsayılan gönderici adresi", |
|||
"DisplayName:Abp.Mailing.DefaultFromDisplayName": "Varsayılan gönderici adı", |
|||
"DisplayName:Abp.Mailing.Smtp.Host": "Sunucu", |
|||
"DisplayName:Abp.Mailing.Smtp.Port": "Port", |
|||
"DisplayName:Abp.Mailing.Smtp.UserName": "Kullanıcı adı", |
|||
"DisplayName:Abp.Mailing.Smtp.Password": "Şifre", |
|||
"DisplayName:Abp.Mailing.Smtp.Domain": "Domain", |
|||
"DisplayName:Abp.Mailing.Smtp.EnableSsl": "SSL aktif", |
|||
"DisplayName:Abp.Mailing.Smtp.UseDefaultCredentials": "Varsayılan kimlik kullan", |
|||
"Description:Abp.Mailing.DefaultFromAddress": "Varsayılan gönderici adresi", |
|||
"Description:Abp.Mailing.DefaultFromDisplayName": "Varsayılan gönderici adı", |
|||
"Description:Abp.Mailing.Smtp.Host": "SMTP üzerinden e-posta göndermek için kullanılacak sunucunun IP adresi ya da adı.", |
|||
"Description:Abp.Mailing.Smtp.Port": "Sunucunun SMTP portu.", |
|||
"Description:Abp.Mailing.Smtp.UserName": "Varsayılan kimlik kullanılmaması durumunda kullanılacak kullanıcı adı.", |
|||
"Description:Abp.Mailing.Smtp.Password": "Varsayılan kimlik kullanılmaması durumunda kullanılacak şifre.", |
|||
"Description:Abp.Mailing.Smtp.Domain": "Kimlik bilgilerinin doğrulanacağı sunucu/domain.", |
|||
"Description:Abp.Mailing.Smtp.EnableSsl": "Email gönderiminde SSL kullanılıp kullanılmayacağı.", |
|||
"Description:Abp.Mailing.Smtp.UseDefaultCredentials": "Varsayılan kimlik bilgilerinin kullanılıp kullanılmayacağı.", |
|||
"TextTemplate:StandardEmailTemplates.Layout": "Varsayılan e-posta layout şablonu", |
|||
"TextTemplate:StandardEmailTemplates.Message": "Basit bir mesaj göndermek için e-posta şablonu" |
|||
} |
|||
} |
|||
@ -1,25 +1,27 @@ |
|||
using Volo.Abp.TextTemplating; |
|||
using Volo.Abp.Emailing.Localization; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.TextTemplating; |
|||
|
|||
namespace Volo.Abp.Emailing.Templates |
|||
{ |
|||
public class DefaultEmailTemplateProvider : TemplateDefinitionProvider |
|||
public class StandardEmailTemplateDefinitionProvider : TemplateDefinitionProvider |
|||
{ |
|||
public override void Define(ITemplateDefinitionContext context) |
|||
{ |
|||
context.Add( |
|||
new TemplateDefinition( |
|||
StandardEmailTemplates.Layout, |
|||
defaultCultureName: "en", |
|||
displayName: LocalizableString.Create<EmailingResource>("TextTemplate:StandardEmailTemplates.Layout"), |
|||
isLayout: true |
|||
).WithVirtualFilePath("/Volo/Abp/Emailing/Templates/Layout") |
|||
).WithVirtualFilePath("/Volo/Abp/Emailing/Templates/Layout.tpl", true) |
|||
); |
|||
|
|||
context.Add( |
|||
new TemplateDefinition( |
|||
StandardEmailTemplates.Message, |
|||
defaultCultureName: "en", |
|||
displayName: LocalizableString.Create<EmailingResource>("TextTemplate:StandardEmailTemplates.Message"), |
|||
layout: StandardEmailTemplates.Layout |
|||
).WithVirtualFilePath("/Volo/Abp/Emailing/Templates/Message") |
|||
).WithVirtualFilePath("/Volo/Abp/Emailing/Templates/Message.tpl", true) |
|||
); |
|||
} |
|||
} |
|||
@ -1,127 +0,0 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.Http.Modeling |
|||
{ |
|||
public static class ModelingTypeHelper |
|||
{ |
|||
public static string GetFullNameHandlingNullableAndGenerics([NotNull] Type type) |
|||
{ |
|||
Check.NotNull(type, nameof(type)); |
|||
|
|||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) |
|||
{ |
|||
return type.GenericTypeArguments[0].FullName + "?"; |
|||
} |
|||
|
|||
if (type.IsGenericType) |
|||
{ |
|||
var genericType = type.GetGenericTypeDefinition(); |
|||
return $"{genericType.FullName.Left(genericType.FullName.IndexOf('`'))}<{type.GenericTypeArguments.Select(GetFullNameHandlingNullableAndGenerics).JoinAsString(",")}>"; |
|||
} |
|||
|
|||
return type.FullName; |
|||
} |
|||
|
|||
public static string GetSimplifiedName([NotNull] Type type) |
|||
{ |
|||
Check.NotNull(type, nameof(type)); |
|||
|
|||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) |
|||
{ |
|||
return GetSimplifiedName(type.GenericTypeArguments[0]) + "?"; |
|||
} |
|||
|
|||
if (type.IsGenericType) |
|||
{ |
|||
var genericType = type.GetGenericTypeDefinition(); |
|||
return $"{genericType.FullName.Left(genericType.FullName.IndexOf('`'))}<{type.GenericTypeArguments.Select(GetSimplifiedName).JoinAsString(",")}>"; |
|||
} |
|||
|
|||
if (type == typeof(string)) |
|||
{ |
|||
return "string"; |
|||
} |
|||
else if (type == typeof(int)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
else if (type == typeof(long)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
else if (type == typeof(bool)) |
|||
{ |
|||
return "boolean"; |
|||
} |
|||
else if (type == typeof(char)) |
|||
{ |
|||
return "string"; |
|||
} |
|||
else if (type == typeof(double)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
else if (type == typeof(float)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
else if (type == typeof(decimal)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
else if (type == typeof(DateTime)) |
|||
{ |
|||
return "string"; |
|||
} |
|||
else if (type == typeof(DateTimeOffset)) |
|||
{ |
|||
return "string"; |
|||
} |
|||
else if (type == typeof(TimeSpan)) |
|||
{ |
|||
return "string"; |
|||
} |
|||
else if (type == typeof(Guid)) |
|||
{ |
|||
return "string"; |
|||
} |
|||
else if (type == typeof(byte)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
else if (type == typeof(sbyte)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
else if (type == typeof(short)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
else if (type == typeof(ushort)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
else if (type == typeof(uint)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
else if (type == typeof(ulong)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
else if (type == typeof(IntPtr)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
else if (type == typeof(UIntPtr)) |
|||
{ |
|||
return "number"; |
|||
} |
|||
|
|||
return type.FullName; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
namespace Microsoft.Extensions.Localization |
|||
{ |
|||
public static class AbpStringLocalizerFactoryExtensions |
|||
{ |
|||
public static IStringLocalizer CreateDefaultOrNull(this IStringLocalizerFactory localizerFactory) |
|||
{ |
|||
return (localizerFactory as IAbpStringLocalizerFactoryWithDefaultResourceSupport) |
|||
?.CreateDefaultOrNull(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Microsoft.Extensions.Localization |
|||
{ |
|||
public interface IAbpStringLocalizerFactoryWithDefaultResourceSupport |
|||
{ |
|||
[CanBeNull] |
|||
IStringLocalizer CreateDefaultOrNull(); |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
using System; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.Extensions.Localization; |
|||
|
|||
namespace Volo.Abp.Localization |
|||
{ |
|||
public static class HasNameWithLocalizableDisplayNameExtensions |
|||
{ |
|||
[NotNull] |
|||
public static string GetLocalizedDisplayName( |
|||
[NotNull] this IHasNameWithLocalizableDisplayName source, |
|||
[NotNull] IStringLocalizerFactory stringLocalizerFactory, |
|||
[CanBeNull] string localizationNamePrefix = "DisplayName:") |
|||
{ |
|||
if (source.DisplayName != null) |
|||
{ |
|||
return source.DisplayName.Localize(stringLocalizerFactory); |
|||
} |
|||
|
|||
var defaultStringLocalizer = stringLocalizerFactory.CreateDefaultOrNull(); |
|||
if (defaultStringLocalizer == null) |
|||
{ |
|||
return source.Name; |
|||
} |
|||
|
|||
var localizedString = defaultStringLocalizer[$"{localizationNamePrefix}{source.Name}"]; |
|||
if (!localizedString.ResourceNotFound || |
|||
localizationNamePrefix.IsNullOrEmpty()) |
|||
{ |
|||
return localizedString; |
|||
} |
|||
|
|||
return defaultStringLocalizer[source.Name]; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.Localization |
|||
{ |
|||
public interface IHasNameWithLocalizableDisplayName |
|||
{ |
|||
[NotNull] |
|||
public string Name { get; } |
|||
|
|||
[CanBeNull] |
|||
public ILocalizableString DisplayName { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.Immutable; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.ObjectExtending.Modularity |
|||
{ |
|||
public class EntityExtensionConfiguration |
|||
{ |
|||
[NotNull] |
|||
protected ExtensionPropertyConfigurationDictionary Properties { get; } |
|||
|
|||
[NotNull] |
|||
public List<Action<ObjectExtensionValidationContext>> Validators { get; } |
|||
|
|||
public Dictionary<string, object> Configuration { get; } |
|||
|
|||
public EntityExtensionConfiguration() |
|||
{ |
|||
Properties = new ExtensionPropertyConfigurationDictionary(); |
|||
Validators = new List<Action<ObjectExtensionValidationContext>>(); |
|||
Configuration = new Dictionary<string, object>(); |
|||
} |
|||
|
|||
[NotNull] |
|||
public virtual EntityExtensionConfiguration AddOrUpdateProperty<TProperty>( |
|||
[NotNull] string propertyName, |
|||
[CanBeNull] Action<ExtensionPropertyConfiguration> configureAction = null) |
|||
{ |
|||
return AddOrUpdateProperty( |
|||
typeof(TProperty), |
|||
propertyName, |
|||
configureAction |
|||
); |
|||
} |
|||
|
|||
[NotNull] |
|||
public virtual EntityExtensionConfiguration AddOrUpdateProperty( |
|||
[NotNull] Type propertyType, |
|||
[NotNull] string propertyName, |
|||
[CanBeNull] Action<ExtensionPropertyConfiguration> configureAction = null) |
|||
{ |
|||
Check.NotNull(propertyType, nameof(propertyType)); |
|||
Check.NotNull(propertyName, nameof(propertyName)); |
|||
|
|||
var propertyInfo = Properties.GetOrAdd( |
|||
propertyName, |
|||
() => new ExtensionPropertyConfiguration(this, propertyType, propertyName) |
|||
); |
|||
|
|||
configureAction?.Invoke(propertyInfo); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
[NotNull] |
|||
public virtual ImmutableList<ExtensionPropertyConfiguration> GetProperties() |
|||
{ |
|||
return Properties.Values.ToImmutableList(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.ObjectExtending.Modularity |
|||
{ |
|||
public class EntityExtensionConfigurationDictionary : Dictionary<string, EntityExtensionConfiguration> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.ObjectExtending.Modularity |
|||
{ |
|||
public class ExtensionPropertyApiConfiguration |
|||
{ |
|||
[NotNull] |
|||
public ExtensionPropertyApiGetConfiguration OnGet { get; } |
|||
|
|||
[NotNull] |
|||
public ExtensionPropertyApiCreateConfiguration OnCreate { get; } |
|||
|
|||
[NotNull] |
|||
public ExtensionPropertyApiUpdateConfiguration OnUpdate { get; } |
|||
|
|||
public ExtensionPropertyApiConfiguration() |
|||
{ |
|||
OnGet = new ExtensionPropertyApiGetConfiguration(); |
|||
OnCreate = new ExtensionPropertyApiCreateConfiguration(); |
|||
OnUpdate = new ExtensionPropertyApiUpdateConfiguration(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
namespace Volo.Abp.ObjectExtending.Modularity |
|||
{ |
|||
public class ExtensionPropertyApiCreateConfiguration |
|||
{ |
|||
/// <summary>
|
|||
/// Default: true.
|
|||
/// </summary>
|
|||
public bool IsAvailable { get; set; } = true; |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
namespace Volo.Abp.ObjectExtending.Modularity |
|||
{ |
|||
public class ExtensionPropertyApiGetConfiguration |
|||
{ |
|||
/// <summary>
|
|||
/// Default: true.
|
|||
/// </summary>
|
|||
public bool IsAvailable { get; set; } = true; |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
namespace Volo.Abp.ObjectExtending.Modularity |
|||
{ |
|||
public class ExtensionPropertyApiUpdateConfiguration |
|||
{ |
|||
/// <summary>
|
|||
/// Default: true.
|
|||
/// </summary>
|
|||
public bool IsAvailable { get; set; } = true; |
|||
} |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace Volo.Abp.ObjectExtending.Modularity |
|||
{ |
|||
public class ExtensionPropertyConfiguration : IHasNameWithLocalizableDisplayName |
|||
{ |
|||
[NotNull] |
|||
public EntityExtensionConfiguration EntityExtensionConfiguration { get; } |
|||
|
|||
[NotNull] |
|||
public string Name { get; } |
|||
|
|||
[NotNull] |
|||
public Type Type { get; } |
|||
|
|||
[NotNull] |
|||
public List<Attribute> Attributes { get; } |
|||
|
|||
[NotNull] |
|||
public List<Action<ObjectExtensionPropertyValidationContext>> Validators { get; } |
|||
|
|||
[CanBeNull] |
|||
public ILocalizableString DisplayName { get; set; } |
|||
|
|||
[NotNull] |
|||
public Dictionary<string, object> Configuration { get; } |
|||
|
|||
/// <summary>
|
|||
/// Single point to enable/disable this property for the clients (UI and API).
|
|||
/// If this is false, the configuration made in the <see cref="UI"/> and the <see cref="Api"/>
|
|||
/// properties are not used.
|
|||
/// Default: true.
|
|||
/// </summary>
|
|||
public bool IsAvailableToClients { get; set; } = true; |
|||
|
|||
[NotNull] |
|||
public ExtensionPropertyEntityConfiguration Entity { get; } |
|||
|
|||
[NotNull] |
|||
public ExtensionPropertyUiConfiguration UI { get; } |
|||
|
|||
[NotNull] |
|||
public ExtensionPropertyApiConfiguration Api { get; } |
|||
|
|||
public ExtensionPropertyConfiguration( |
|||
[NotNull] EntityExtensionConfiguration entityExtensionConfiguration, |
|||
[NotNull] Type type, |
|||
[NotNull] string name) |
|||
{ |
|||
EntityExtensionConfiguration = Check.NotNull(entityExtensionConfiguration, nameof(entityExtensionConfiguration)); |
|||
Type = Check.NotNull(type, nameof(type)); |
|||
Name = Check.NotNull(name, nameof(name)); |
|||
|
|||
Configuration = new Dictionary<string, object>(); |
|||
Attributes = new List<Attribute>(); |
|||
Validators = new List<Action<ObjectExtensionPropertyValidationContext>>(); |
|||
|
|||
Entity = new ExtensionPropertyEntityConfiguration(); |
|||
UI = new ExtensionPropertyUiConfiguration(); |
|||
Api = new ExtensionPropertyApiConfiguration(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.ObjectExtending.Modularity |
|||
{ |
|||
public class ExtensionPropertyConfigurationDictionary : Dictionary<string, ExtensionPropertyConfiguration> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue