Browse Source

Merge branch 'dev' of https://github.com/abpframework/abp into dev

pull/4003/head
Alper Ebicoglu 6 years ago
parent
commit
15a76b51a7
  1. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  2. 21
      docs/en/Dapper.md
  3. 8
      docs/en/Object-Extensions.md
  4. 1
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs
  5. 7
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs
  6. 8
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs
  7. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs
  8. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerStyleContributor.cs
  9. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Luxon/LuxonScriptContributor.cs
  10. 1
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs
  11. 1
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs
  12. 30
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js
  13. 26
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/ui-extensions.js
  14. 133
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/ObjectExtending/MvcUiObjectExtensionPropertyInfoExtensions.cs
  15. 24
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/CachedObjectExtensionsDtoService.cs
  16. 113
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/ObjectExtending/ObjectExtendingPropertyInfoExtensions.cs
  17. 38
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/IBasicObjectExtensionPropertyInfo.cs
  18. 2
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfiguration.cs
  19. 1
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs
  20. 2
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs
  21. 6
      framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/en.json
  22. 12
      modules/blogging/src/Volo.Blogging.Web/BloggingTwitterOptions.cs
  23. 6
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml
  24. 7
      modules/blogging/src/Volo.Blogging.Web/SocialMedia/BloggingTwitterOptions.cs
  25. 23
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs
  26. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj
  27. 2
      templates/module/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj

4
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json

@ -150,6 +150,8 @@
"DiscountRequestDeletionWarningMessage": "Discount request will be deleted" , "DiscountRequestDeletionWarningMessage": "Discount request will be deleted" ,
"BusinessType": "Business Type", "BusinessType": "Business Type",
"TotalQuestionCount": "Total question count", "TotalQuestionCount": "Total question count",
"RemainingQuestionCount": "Remaining question count" "RemainingQuestionCount": "Remaining question count",
"TotalQuestionMustBeGreaterWarningMessage": "TotalQuestionCount must be greater than RemainingQuestionCount !",
"QuestionCountsMustBeGreaterThanZero": "TotalQuestionCount and RemainingQuestionCount must be zero or greater than zero !"
} }
} }

21
docs/en/Dapper.md

@ -1,22 +1,24 @@
# Dapper Integration # Dapper Integration
Because Dapper's idea is that the sql statement takes precedence, and mainly provides some extension methods for the `IDbConnection` interface. Dapper is a light-weight and simple database provider. The major benefit of using Dapper is writing T-SQL queries. It provides some extension methods for `IDbConnection` interface.
Abp does not encapsulate too many functions for Dapper. Abp Dapper provides a `DapperRepository<TDbContext>` base class based on Abp EntityFrameworkCore, which provides the `IDbConnection` and `IDbTransaction` properties required by Dapper. ABP does not encapsulate many functions for Dapper. ABP Dapper library provides a `DapperRepository<TDbContext>` base class based on ABP EntityFrameworkCore module, which provides the `IDbConnection` and `IDbTransaction` properties required by Dapper. `IDbConnection` and `IDbTransaction` works well with the [ABP Unit-Of-Work](Unit-Of-Work.md).
These two properties can work well with [Unit-Of-Work](Unit-Of-Work.md).
## Installation ## Installation
Please install and configure EF Core according to [EF Core's integrated documentation](Entity-Framework-Core.md). Install and configure EF Core according to [EF Core's integrated documentation](Entity-Framework-Core.md).
`Volo.Abp.Dapper` is the library for the Dapper integration.
You can find it on NuGet Gallery: https://www.nuget.org/packages/Volo.Abp.Dapper
`Volo.Abp.Dapper` is the main nuget package for the Dapper integration. Install it to your project (for a layered application, to your data/infrastructure layer): Install it to your project (for a layered application, to your data/infrastructure layer):
```shell ```shell
Install-Package Volo.Abp.Dapper Install-Package Volo.Abp.Dapper
``` ```
Then add `AbpDapperModule` module dependency (`DependsOn` attribute) to your [module](Module-Development-Basics.md): Then add `AbpDapperModule` module dependency (with `DependsOn` attribute) to your [module](Module-Development-Basics.md):
````C# ````C#
using Volo.Abp.Dapper; using Volo.Abp.Dapper;
@ -34,9 +36,10 @@ namespace MyCompany.MyProject
## Implement Dapper Repository ## Implement Dapper Repository
The following code implements the `Person` repository, which requires EF Core's `DbContext` (MyAppDbContext). You can inject `PersonDapperRepository` to call its methods. The following code creates the `PersonRepository`, which requires EF Core's `DbContext` (MyAppDbContext).
You can inject `PersonDapperRepository` to your services for your database operations.
`DbConnection` and `DbTransaction` are from the `DapperRepository` base class. `DbConnection` and `DbTransaction` comes from the `DapperRepository` base class.
```C# ```C#
public class PersonDapperRepository : DapperRepository<MyAppDbContext>, ITransientDependency public class PersonDapperRepository : DapperRepository<MyAppDbContext>, ITransientDependency

8
docs/en/Object-Extensions.md

@ -200,17 +200,17 @@ ObjectExtensionManager.Instance
````csharp ````csharp
ObjectExtensionManager.Instance ObjectExtensionManager.Instance
.AddOrUpdateProperty<IdentityUser, int>( .AddOrUpdateProperty<IdentityUser, DateTime>(
"MyIntProperty", "MyDateTimeProperty",
options => options =>
{ {
options.DefaultValueFactory = () => 42; options.DefaultValueFactory = () => DateTime.Now;
}); });
```` ````
`options.DefaultValueFactory` has a higher priority than the `options.DefaultValue` . `options.DefaultValueFactory` has a higher priority than the `options.DefaultValue` .
> Tip: Use `DefaultValueFactory` option only if the default value may change over the time. If it is a constant value, then use the `DefaultValue` option. > Tip: Use `DefaultValueFactory` option only if the default value may change over the time (like `DateTime.Now` in this example). If it is a constant value, then use the `DefaultValue` option.
#### CheckPairDefinitionOnMapping #### CheckPairDefinitionOnMapping

1
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs

@ -2,7 +2,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using Volo.Abp.Threading;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions
{ {

7
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs

@ -33,6 +33,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
[ViewContext] [ViewContext]
public ViewContext ViewContext { get; set; } public ViewContext ViewContext { get; set; }
[HtmlAttributeName("asp-format")]
public string Format { get; set; }
public string Name { get; set; }
public string Value { get; set; }
public AbpInputTagHelper(AbpInputTagHelperService tagHelperService) public AbpInputTagHelper(AbpInputTagHelperService tagHelperService)
: base(tagHelperService) : base(tagHelperService)
{ {

8
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs

@ -110,7 +110,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return new TextAreaTagHelper(_generator) return new TextAreaTagHelper(_generator)
{ {
For = TagHelper.AspFor, For = TagHelper.AspFor,
ViewContext = TagHelper.ViewContext ViewContext = TagHelper.ViewContext,
Name = TagHelper.Name
}; };
} }
@ -118,7 +119,10 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{ {
For = TagHelper.AspFor, For = TagHelper.AspFor,
InputTypeName = TagHelper.InputTypeName, InputTypeName = TagHelper.InputTypeName,
ViewContext = TagHelper.ViewContext ViewContext = TagHelper.ViewContext,
Format = TagHelper.Format,
Name = TagHelper.Name,
Value = TagHelper.Value
}; };
} }

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs

@ -4,7 +4,7 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery; using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Timeago namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker
{ {
[DependsOn(typeof(JQueryScriptContributor))] [DependsOn(typeof(JQueryScriptContributor))]
public class BootstrapDatepickerScriptContributor : BundleContributor public class BootstrapDatepickerScriptContributor : BundleContributor

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerStyleContributor.cs

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Select2 namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker
{ {
public class BootstrapDatepickerStyleContributor : BundleContributor public class BootstrapDatepickerStyleContributor : BundleContributor
{ {

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Luxon/LuxonScriptContributor.cs

@ -1,6 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Luxon namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Luxon

1
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs

@ -1,5 +1,6 @@
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.Bootstrap; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Bootstrap;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.DatatablesNetBs4; using Volo.Abp.AspNetCore.Mvc.UI.Packages.DatatablesNetBs4;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery; using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryForm; using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryForm;

1
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs

@ -1,5 +1,6 @@
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.Bootstrap; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Bootstrap;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.Core; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Core;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.DatatablesNetBs4; using Volo.Abp.AspNetCore.Mvc.UI.Packages.DatatablesNetBs4;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.FontAwesome; using Volo.Abp.AspNetCore.Mvc.UI.Packages.FontAwesome;

30
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js

@ -8,7 +8,7 @@
}; };
/************************************************************************ /************************************************************************
* RECORD-ACTIONS extension for datatables * * RECORD-ACTIONS extension for datatables *
*************************************************************************/ *************************************************************************/
(function () { (function () {
if (!$.fn.dataTableExt) { if (!$.fn.dataTableExt) {
@ -328,4 +328,32 @@
})(); })();
/************************************************************************
* Default Renderers *
*************************************************************************/
datatables.defaultRenderers = datatables.defaultRenderers || {};
datatables.defaultRenderers['boolean'] = function(value) {
if (value) {
return '<i class="fa fa-check"></i>';
} else {
return '<i class="fa fa-times"></i>';
}
};
datatables.defaultRenderers['date'] = function (value) {
return luxon
.DateTime
.fromISO(value, { locale: abp.localization.currentCulture.name })
.toLocaleString();
};
datatables.defaultRenderers['datetime'] = function (value) {
return luxon
.DateTime
.fromISO(value, { locale: abp.localization.currentCulture.name })
.toLocaleString(luxon.DateTime.DATETIME_SHORT);
};
})(jQuery); })(jQuery);

26
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/ui-extensions.js

@ -96,7 +96,7 @@
get: _get get: _get
}; };
})(); })();
function initializeObjectExtensions() { function initializeObjectExtensions() {
var getShortEnumTypeName = function (enumType) { var getShortEnumTypeName = function (enumType) {
@ -150,10 +150,9 @@
return defaultValue; return defaultValue;
} }
function localizeEnumMember(property, row) { function localizeEnumMember(property, enumMemberValue) {
var enumType = property.config.type; var enumType = property.config.type;
var enumInfo = abp.objectExtensions.enums[enumType]; var enumInfo = abp.objectExtensions.enums[enumType];
var enumMemberValue = row.extraProperties[property.name];
var enumMemberName = getEnumMemberName(enumInfo, enumMemberValue); var enumMemberName = getEnumMemberName(enumInfo, enumMemberValue);
if (!enumMemberName) { if (!enumMemberName) {
@ -199,6 +198,10 @@
return tableProperties; return tableProperties;
} }
function getValueFromRow(property, row) {
return row.extraProperties[property.name];;
}
function convertPropertyToColumnConfig(property) { function convertPropertyToColumnConfig(property) {
var columnConfig = { var columnConfig = {
title: localizeDisplayName(property.name, property.config.displayName), title: localizeDisplayName(property.name, property.config.displayName),
@ -206,12 +209,19 @@
orderable: false orderable: false
}; };
if (property.config.typeSimple === 'enum') { if (property.config.typeSimple === 'enum') {
columnConfig.render = function (data, type, row) { columnConfig.render = function(data, type, row) {
return localizeEnumMember( var value = getValueFromRow(property, row);
property, return localizeEnumMember(property, value);
row }
); } else {
var defaultRenderer = abp.libs.datatables.defaultRenderers[property.config.typeSimple];
if (defaultRenderer) {
columnConfig.render = function (data, type, row) {
var value = getValueFromRow(property, row);
return defaultRenderer(value);
}
} }
} }

133
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/ObjectExtending/MvcUiObjectExtensionPropertyInfoExtensions.cs

@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
namespace Volo.Abp.ObjectExtending
{
public static class MvcUiObjectExtensionPropertyInfoExtensions
{
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?)
};
public static string GetInputFormatOrNull(this IBasicObjectExtensionPropertyInfo property)
{
if (property.IsDate())
{
return "{0:yyyy-MM-dd}";
}
if (property.IsDateTime())
{
return "{0:yyyy-MM-ddTHH:mm}";
}
return null;
}
public static string 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 (NumberTypes.Contains(type))
{
return "number";
}
return null;
}
}
}

24
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/CachedObjectExtensionsDtoService.cs

@ -107,9 +107,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending
var extensionPropertyDto = new ExtensionPropertyDto var extensionPropertyDto = new ExtensionPropertyDto
{ {
Type = TypeHelper.GetFullNameHandlingNullableAndGenerics(propertyConfig.Type), Type = TypeHelper.GetFullNameHandlingNullableAndGenerics(propertyConfig.Type),
TypeSimple = propertyConfig.Type.IsEnum TypeSimple = GetSimpleTypeName(propertyConfig),
? "enum"
: TypeHelper.GetSimplifiedName(propertyConfig.Type),
Attributes = new List<ExtensionPropertyAttributeDto>(), Attributes = new List<ExtensionPropertyAttributeDto>(),
DisplayName = CreateDisplayNameDto(propertyConfig), DisplayName = CreateDisplayNameDto(propertyConfig),
Configuration = new Dictionary<string, object>(), Configuration = new Dictionary<string, object>(),
@ -161,6 +159,26 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending
return extensionPropertyDto; return extensionPropertyDto;
} }
protected virtual string GetSimpleTypeName(ExtensionPropertyConfiguration propertyConfig)
{
if (propertyConfig.Type.IsEnum)
{
return "enum";
}
if (propertyConfig.IsDate())
{
return "date";
}
if (propertyConfig.IsDateTime())
{
return "datetime";
}
return TypeHelper.GetSimplifiedName(propertyConfig.Type);
}
protected virtual LocalizableStringDto CreateDisplayNameDto(ExtensionPropertyConfiguration propertyConfig) protected virtual LocalizableStringDto CreateDisplayNameDto(ExtensionPropertyConfiguration propertyConfig)
{ {
if (propertyConfig.DisplayName == null) if (propertyConfig.DisplayName == null)

113
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/ObjectExtending/ObjectExtendingPropertyInfoExtensions.cs

@ -1,116 +1,35 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc; using System.Linq;
namespace Volo.Abp.ObjectExtending namespace Volo.Abp.ObjectExtending
{ {
public static class ObjectExtensionPropertyInfoAspNetCoreMvcExtensions public static class ObjectExtensionPropertyInfoAspNetCoreMvcExtensions
{ {
private static readonly HashSet<Type> NumberTypes = new HashSet<Type> { private static readonly Type[] DateTimeTypes =
typeof(int), {
typeof(long), typeof(DateTime),
typeof(byte), typeof(DateTimeOffset)
typeof(sbyte),
typeof(short),
typeof(ushort),
typeof(uint),
typeof(long),
typeof(ulong),
typeof(float),
typeof(double),
typeof(int?),
typeof(long?),
typeof(byte?),
typeof(sbyte?),
typeof(short?),
typeof(ushort?),
typeof(uint?),
typeof(long?),
typeof(ulong?),
typeof(float?),
typeof(double?),
}; };
public static string GetInputType(this ObjectExtensionPropertyInfo propertyInfo) public static bool IsDate(this IBasicObjectExtensionPropertyInfo property)
{ {
foreach (var attribute in propertyInfo.Attributes) return DateTimeTypes.Contains(property.Type) &&
{ property.GetDataTypeOrNull() == DataType.Date;
var inputTypeByAttribute = GetInputTypeFromAttributeOrNull(attribute);
if (inputTypeByAttribute != null)
{
return inputTypeByAttribute;
}
}
return GetInputTypeFromTypeOrNull(propertyInfo.Type)
?? "text"; //default
} }
private static string GetInputTypeFromAttributeOrNull(Attribute attribute) public static bool IsDateTime(this IBasicObjectExtensionPropertyInfo property)
{ {
if (attribute is EmailAddressAttribute) return DateTimeTypes.Contains(property.Type) &&
{ !property.IsDate();
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) public static DataType? GetDataTypeOrNull(this IBasicObjectExtensionPropertyInfo property)
{ {
if (type == typeof(bool)) return property
{ .Attributes
return "checkbox"; .OfType<DataTypeAttribute>()
} .FirstOrDefault()?.DataType;
if (type == typeof(DateTime))
{
return "datetime-local";
}
if (NumberTypes.Contains(type))
{
return "number";
}
return null;
} }
} }
} }

38
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/IBasicObjectExtensionPropertyInfo.cs

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Localization;
namespace Volo.Abp.ObjectExtending
{
public interface IBasicObjectExtensionPropertyInfo
{
[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; }
/// <summary>
/// Uses as the default value if <see cref="DefaultValueFactory"/> was not set.
/// </summary>
[CanBeNull]
public object DefaultValue { get; set; }
/// <summary>
/// Used with the first priority to create the default value for the property.
/// Uses to the <see cref="DefaultValue"/> if this was not set.
/// </summary>
[CanBeNull]
public Func<object> DefaultValueFactory { get; set; }
}
}

2
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfiguration.cs

@ -6,7 +6,7 @@ using Volo.Abp.Reflection;
namespace Volo.Abp.ObjectExtending.Modularity namespace Volo.Abp.ObjectExtending.Modularity
{ {
public class ExtensionPropertyConfiguration : IHasNameWithLocalizableDisplayName public class ExtensionPropertyConfiguration : IHasNameWithLocalizableDisplayName, IBasicObjectExtensionPropertyInfo
{ {
[NotNull] [NotNull]
public EntityExtensionConfiguration EntityExtensionConfiguration { get; } public EntityExtensionConfiguration EntityExtensionConfiguration { get; }

1
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices;
using JetBrains.Annotations; using JetBrains.Annotations;
namespace Volo.Abp.ObjectExtending.Modularity namespace Volo.Abp.ObjectExtending.Modularity

2
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs

@ -7,7 +7,7 @@ using Volo.Abp.Reflection;
namespace Volo.Abp.ObjectExtending namespace Volo.Abp.ObjectExtending
{ {
public class ObjectExtensionPropertyInfo : IHasNameWithLocalizableDisplayName public class ObjectExtensionPropertyInfo : IHasNameWithLocalizableDisplayName, IBasicObjectExtensionPropertyInfo
{ {
[NotNull] [NotNull]
public ObjectExtensionInfo ObjectExtension { get; } public ObjectExtensionInfo ObjectExtension { get; }

6
framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/en.json

@ -0,0 +1,6 @@
{
"culture": "de",
"texts": {
"hello": "Hello"
}
}

12
modules/blogging/src/Volo.Blogging.Web/BloggingTwitterOptions.cs

@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Volo.Blogging
{
public class BloggingTwitterOptions
{
public string Site { get; set; }
}
}

6
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml

@ -8,6 +8,7 @@
@using Volo.Blogging.Pages.Blog.Posts @using Volo.Blogging.Pages.Blog.Posts
@using Volo.Blogging.Areas.Blog.Helpers.TagHelpers @using Volo.Blogging.Areas.Blog.Helpers.TagHelpers
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Prismjs @using Volo.Abp.AspNetCore.Mvc.UI.Packages.Prismjs
@using Volo.Blogging.SocialMedia
@inject IAuthorizationService Authorization @inject IAuthorizationService Authorization
@inject IOptionsSnapshot<BloggingTwitterOptions> twitterOptions @inject IOptionsSnapshot<BloggingTwitterOptions> twitterOptions
@model DetailModel @model DetailModel
@ -21,6 +22,11 @@
ViewBag.TwitterDescription = Model.Post.Description; ViewBag.TwitterDescription = Model.Post.Description;
ViewBag.TwitterImage = $"{Request.Scheme}://{Request.Host}{Request.PathBase}{Model.Post.CoverImage}"; ViewBag.TwitterImage = $"{Request.Scheme}://{Request.Host}{Request.PathBase}{Model.Post.CoverImage}";
ViewBag.LinkedInUrl = Request.GetEncodedUrl();
ViewBag.LinkedInTitle = Model.Post.Title;
ViewBag.LinkedInDescription = Model.Post.Description;
ViewBag.LinkedInImage = $"{Request.Scheme}://{Request.Host}{Request.PathBase}{Model.Post.CoverImage}";
var hasCommentingPermission = CurrentUser.IsAuthenticated; //TODO: Apply real policy! var hasCommentingPermission = CurrentUser.IsAuthenticated; //TODO: Apply real policy!
} }
@section scripts { @section scripts {

7
modules/blogging/src/Volo.Blogging.Web/SocialMedia/BloggingTwitterOptions.cs

@ -0,0 +1,7 @@
namespace Volo.Blogging.SocialMedia
{
public class BloggingTwitterOptions
{
public string Site { get; set; }
}
}

23
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs

@ -15,13 +15,13 @@ namespace Volo.Abp.Identity.MongoDB
{ {
public class MongoIdentityUserRepository : MongoDbRepository<IAbpIdentityMongoDbContext, IdentityUser, Guid>, IIdentityUserRepository public class MongoIdentityUserRepository : MongoDbRepository<IAbpIdentityMongoDbContext, IdentityUser, Guid>, IIdentityUserRepository
{ {
public MongoIdentityUserRepository(IMongoDbContextProvider<IAbpIdentityMongoDbContext> dbContextProvider) public MongoIdentityUserRepository(IMongoDbContextProvider<IAbpIdentityMongoDbContext> dbContextProvider)
: base(dbContextProvider) : base(dbContextProvider)
{ {
} }
public virtual async Task<IdentityUser> FindByNormalizedUserNameAsync( public virtual async Task<IdentityUser> FindByNormalizedUserNameAsync(
string normalizedUserName, string normalizedUserName,
bool includeDetails = true, bool includeDetails = true,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
@ -33,7 +33,7 @@ namespace Volo.Abp.Identity.MongoDB
} }
public virtual async Task<List<string>> GetRoleNamesAsync( public virtual async Task<List<string>> GetRoleNamesAsync(
Guid id, Guid id,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)); var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken));
@ -42,8 +42,8 @@ namespace Volo.Abp.Identity.MongoDB
} }
public virtual async Task<IdentityUser> FindByLoginAsync( public virtual async Task<IdentityUser> FindByLoginAsync(
string loginProvider, string loginProvider,
string providerKey, string providerKey,
bool includeDetails = true, bool includeDetails = true,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
@ -71,7 +71,7 @@ namespace Volo.Abp.Identity.MongoDB
} }
public virtual async Task<List<IdentityUser>> GetListByNormalizedRoleNameAsync( public virtual async Task<List<IdentityUser>> GetListByNormalizedRoleNameAsync(
string normalizedRoleName, string normalizedRoleName,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
@ -89,9 +89,9 @@ namespace Volo.Abp.Identity.MongoDB
public virtual async Task<List<IdentityUser>> GetListAsync( public virtual async Task<List<IdentityUser>> GetListAsync(
string sorting = null, string sorting = null,
int maxResultCount = int.MaxValue, int maxResultCount = int.MaxValue,
int skipCount = 0, int skipCount = 0,
string filter = null, string filter = null,
bool includeDetails = false, bool includeDetails = false,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
@ -100,7 +100,8 @@ namespace Volo.Abp.Identity.MongoDB
!filter.IsNullOrWhiteSpace(), !filter.IsNullOrWhiteSpace(),
u => u =>
u.UserName.Contains(filter) || u.UserName.Contains(filter) ||
u.Email.Contains(filter) u.Email.Contains(filter) ||
(u.PhoneNumber != null && u.PhoneNumber.Contains(filter))
) )
.OrderBy(sorting ?? nameof(IdentityUser.UserName)) .OrderBy(sorting ?? nameof(IdentityUser.UserName))
.As<IMongoQueryable<IdentityUser>>() .As<IMongoQueryable<IdentityUser>>()
@ -132,4 +133,4 @@ namespace Volo.Abp.Identity.MongoDB
.LongCountAsync(GetCancellationToken(cancellationToken)); .LongCountAsync(GetCancellationToken(cancellationToken));
} }
} }
} }

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj

@ -3,7 +3,7 @@
<Import Project="..\..\common.props" /> <Import Project="..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>MyCompanyName.MyProjectName</RootNamespace> <RootNamespace>MyCompanyName.MyProjectName</RootNamespace>
</PropertyGroup> </PropertyGroup>

2
templates/module/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj

@ -3,7 +3,7 @@
<Import Project="..\..\common.props" /> <Import Project="..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>MyCompanyName.MyProjectName</RootNamespace> <RootNamespace>MyCompanyName.MyProjectName</RootNamespace>
</PropertyGroup> </PropertyGroup>

Loading…
Cancel
Save