diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index 6ce9c8c1bf..c6010b777b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -150,6 +150,8 @@ "DiscountRequestDeletionWarningMessage": "Discount request will be deleted" , "BusinessType": "Business Type", "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 !" } } \ No newline at end of file diff --git a/docs/en/Dapper.md b/docs/en/Dapper.md index d8b17838eb..26fbf97e66 100644 --- a/docs/en/Dapper.md +++ b/docs/en/Dapper.md @@ -1,22 +1,24 @@ # 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` base class based on Abp EntityFrameworkCore, which provides the `IDbConnection` and `IDbTransaction` properties required by Dapper. - -These two properties can work well with [Unit-Of-Work](Unit-Of-Work.md). +ABP does not encapsulate many functions for Dapper. ABP Dapper library provides a `DapperRepository` 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). ## 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 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# using Volo.Abp.Dapper; @@ -34,9 +36,10 @@ namespace MyCompany.MyProject ## 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# public class PersonDapperRepository : DapperRepository, ITransientDependency diff --git a/docs/en/Object-Extensions.md b/docs/en/Object-Extensions.md index 40a7ddd5ea..8c7cca4037 100644 --- a/docs/en/Object-Extensions.md +++ b/docs/en/Object-Extensions.md @@ -200,17 +200,17 @@ ObjectExtensionManager.Instance ````csharp ObjectExtensionManager.Instance - .AddOrUpdateProperty( - "MyIntProperty", + .AddOrUpdateProperty( + "MyDateTimeProperty", options => { - options.DefaultValueFactory = () => 42; + options.DefaultValueFactory = () => DateTime.Now; }); ```` `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 diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs index d925fd11e8..af961a2bf6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Extensions/TagHelperExtensions.cs @@ -2,7 +2,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.TagHelpers; using System.Text.Encodings.Web; -using Volo.Abp.Threading; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs index f264d21cd5..16a700f4bc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs +++ b/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] 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) : base(tagHelperService) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs index a2bb92a14d..b03b0c8b69 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs +++ b/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) { 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, InputTypeName = TagHelper.InputTypeName, - ViewContext = TagHelper.ViewContext + ViewContext = TagHelper.ViewContext, + Format = TagHelper.Format, + Name = TagHelper.Name, + Value = TagHelper.Value }; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs index 7e21c8cef5..5a32cb7ca0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerScriptContributor.cs +++ b/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.Modularity; -namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Timeago +namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.BootstrapDatepicker { [DependsOn(typeof(JQueryScriptContributor))] public class BootstrapDatepickerScriptContributor : BundleContributor diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerStyleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerStyleContributor.cs index bc345e34b3..0b9b555e97 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/BootstrapDatepicker/BootstrapDatepickerStyleContributor.cs +++ b/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 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 { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Luxon/LuxonScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Luxon/LuxonScriptContributor.cs index e605f6e6ae..3d2a1dc774 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Luxon/LuxonScriptContributor.cs +++ b/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.Text; +using System.Collections.Generic; using Volo.Abp.AspNetCore.Mvc.UI.Bundling; namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Luxon diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs index 892f0d497a..4ff7430553 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs +++ b/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.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.JQuery; using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryForm; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs index d1703113d0..49b8c4893e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalStyleContributor.cs +++ b/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.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.DatatablesNetBs4; using Volo.Abp.AspNetCore.Mvc.UI.Packages.FontAwesome; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js index cd31e73bc4..40aebbc71f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js +++ b/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 () { if (!$.fn.dataTableExt) { @@ -328,4 +328,32 @@ })(); + /************************************************************************ + * Default Renderers * + *************************************************************************/ + + datatables.defaultRenderers = datatables.defaultRenderers || {}; + + datatables.defaultRenderers['boolean'] = function(value) { + if (value) { + return ''; + } else { + return ''; + } + }; + + 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); \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/ui-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/ui-extensions.js index dbf73618ad..eacfecc867 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/ui-extensions.js +++ b/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 }; })(); - + function initializeObjectExtensions() { var getShortEnumTypeName = function (enumType) { @@ -150,10 +150,9 @@ return defaultValue; } - function localizeEnumMember(property, row) { + function localizeEnumMember(property, enumMemberValue) { var enumType = property.config.type; var enumInfo = abp.objectExtensions.enums[enumType]; - var enumMemberValue = row.extraProperties[property.name]; var enumMemberName = getEnumMemberName(enumInfo, enumMemberValue); if (!enumMemberName) { @@ -199,6 +198,10 @@ return tableProperties; } + function getValueFromRow(property, row) { + return row.extraProperties[property.name];; + } + function convertPropertyToColumnConfig(property) { var columnConfig = { title: localizeDisplayName(property.name, property.config.displayName), @@ -206,12 +209,19 @@ orderable: false }; + if (property.config.typeSimple === 'enum') { - columnConfig.render = function (data, type, row) { - return localizeEnumMember( - property, - row - ); + columnConfig.render = function(data, type, row) { + var value = getValueFromRow(property, row); + return localizeEnumMember(property, value); + } + } 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); + } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/ObjectExtending/MvcUiObjectExtensionPropertyInfoExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/ObjectExtending/MvcUiObjectExtensionPropertyInfoExtensions.cs new file mode 100644 index 0000000000..1ebe486068 --- /dev/null +++ b/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 NumberTypes = new HashSet { + 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; + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/CachedObjectExtensionsDtoService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/CachedObjectExtensionsDtoService.cs index 870ff0368e..76d73820b2 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/CachedObjectExtensionsDtoService.cs +++ b/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 { Type = TypeHelper.GetFullNameHandlingNullableAndGenerics(propertyConfig.Type), - TypeSimple = propertyConfig.Type.IsEnum - ? "enum" - : TypeHelper.GetSimplifiedName(propertyConfig.Type), + TypeSimple = GetSimpleTypeName(propertyConfig), Attributes = new List(), DisplayName = CreateDisplayNameDto(propertyConfig), Configuration = new Dictionary(), @@ -161,6 +159,26 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending 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) { if (propertyConfig.DisplayName == null) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/ObjectExtending/ObjectExtendingPropertyInfoExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/ObjectExtending/ObjectExtendingPropertyInfoExtensions.cs index 04339eedd3..dc8a28e89f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/ObjectExtending/ObjectExtendingPropertyInfoExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/ObjectExtending/ObjectExtendingPropertyInfoExtensions.cs @@ -1,116 +1,35 @@ using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using Microsoft.AspNetCore.Mvc; +using System.Linq; namespace Volo.Abp.ObjectExtending { public static class ObjectExtensionPropertyInfoAspNetCoreMvcExtensions { - private static readonly HashSet NumberTypes = new HashSet { - typeof(int), - typeof(long), - typeof(byte), - 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?), + private static readonly Type[] DateTimeTypes = + { + typeof(DateTime), + typeof(DateTimeOffset) }; - public static string GetInputType(this ObjectExtensionPropertyInfo propertyInfo) + public static bool IsDate(this IBasicObjectExtensionPropertyInfo property) { - foreach (var attribute in propertyInfo.Attributes) - { - var inputTypeByAttribute = GetInputTypeFromAttributeOrNull(attribute); - if (inputTypeByAttribute != null) - { - return inputTypeByAttribute; - } - } - - return GetInputTypeFromTypeOrNull(propertyInfo.Type) - ?? "text"; //default + return DateTimeTypes.Contains(property.Type) && + property.GetDataTypeOrNull() == DataType.Date; } - private static string GetInputTypeFromAttributeOrNull(Attribute attribute) + public static bool IsDateTime(this IBasicObjectExtensionPropertyInfo property) { - 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; + return DateTimeTypes.Contains(property.Type) && + !property.IsDate(); } - private static string GetInputTypeFromTypeOrNull(Type type) + public static DataType? GetDataTypeOrNull(this IBasicObjectExtensionPropertyInfo property) { - if (type == typeof(bool)) - { - return "checkbox"; - } - - if (type == typeof(DateTime)) - { - return "datetime-local"; - } - - if (NumberTypes.Contains(type)) - { - return "number"; - } - - return null; + return property + .Attributes + .OfType() + .FirstOrDefault()?.DataType; } } } diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/IBasicObjectExtensionPropertyInfo.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/IBasicObjectExtensionPropertyInfo.cs new file mode 100644 index 0000000000..de9bb35b01 --- /dev/null +++ b/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 Attributes { get; } + + [NotNull] + public List> Validators { get; } + + [CanBeNull] + public ILocalizableString DisplayName { get; } + + /// + /// Uses as the default value if was not set. + /// + [CanBeNull] + public object DefaultValue { get; set; } + + /// + /// Used with the first priority to create the default value for the property. + /// Uses to the if this was not set. + /// + [CanBeNull] + public Func DefaultValueFactory { get; set; } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfiguration.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfiguration.cs index 6d66e51337..0a19a82018 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfiguration.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyConfiguration.cs @@ -6,7 +6,7 @@ using Volo.Abp.Reflection; namespace Volo.Abp.ObjectExtending.Modularity { - public class ExtensionPropertyConfiguration : IHasNameWithLocalizableDisplayName + public class ExtensionPropertyConfiguration : IHasNameWithLocalizableDisplayName, IBasicObjectExtensionPropertyInfo { [NotNull] public EntityExtensionConfiguration EntityExtensionConfiguration { get; } diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs index cb5be17c1f..f4a5b149d6 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using JetBrains.Annotations; namespace Volo.Abp.ObjectExtending.Modularity diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs index 12b32ab241..ddd8fbbc3c 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs @@ -7,7 +7,7 @@ using Volo.Abp.Reflection; namespace Volo.Abp.ObjectExtending { - public class ObjectExtensionPropertyInfo : IHasNameWithLocalizableDisplayName + public class ObjectExtensionPropertyInfo : IHasNameWithLocalizableDisplayName, IBasicObjectExtensionPropertyInfo { [NotNull] public ObjectExtensionInfo ObjectExtension { get; } diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/en.json b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/en.json new file mode 100644 index 0000000000..70d0b2b52e --- /dev/null +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/en.json @@ -0,0 +1,6 @@ +{ + "culture": "de", + "texts": { + "hello": "Hello" + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/BloggingTwitterOptions.cs b/modules/blogging/src/Volo.Blogging.Web/BloggingTwitterOptions.cs deleted file mode 100644 index 8c1b1fbf7d..0000000000 --- a/modules/blogging/src/Volo.Blogging.Web/BloggingTwitterOptions.cs +++ /dev/null @@ -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; } - } -} diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml index 63cfbf8a8e..db6427e2a7 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml @@ -8,6 +8,7 @@ @using Volo.Blogging.Pages.Blog.Posts @using Volo.Blogging.Areas.Blog.Helpers.TagHelpers @using Volo.Abp.AspNetCore.Mvc.UI.Packages.Prismjs +@using Volo.Blogging.SocialMedia @inject IAuthorizationService Authorization @inject IOptionsSnapshot twitterOptions @model DetailModel @@ -21,6 +22,11 @@ ViewBag.TwitterDescription = Model.Post.Description; 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! } @section scripts { diff --git a/modules/blogging/src/Volo.Blogging.Web/SocialMedia/BloggingTwitterOptions.cs b/modules/blogging/src/Volo.Blogging.Web/SocialMedia/BloggingTwitterOptions.cs new file mode 100644 index 0000000000..5960be21b9 --- /dev/null +++ b/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; } + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs index 9eb1664bd5..52a345b0c4 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs +++ b/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, IIdentityUserRepository { - public MongoIdentityUserRepository(IMongoDbContextProvider dbContextProvider) + public MongoIdentityUserRepository(IMongoDbContextProvider dbContextProvider) : base(dbContextProvider) { } public virtual async Task FindByNormalizedUserNameAsync( - string normalizedUserName, + string normalizedUserName, bool includeDetails = true, CancellationToken cancellationToken = default) { @@ -33,7 +33,7 @@ namespace Volo.Abp.Identity.MongoDB } public virtual async Task> GetRoleNamesAsync( - Guid id, + Guid id, CancellationToken cancellationToken = default) { var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)); @@ -42,8 +42,8 @@ namespace Volo.Abp.Identity.MongoDB } public virtual async Task FindByLoginAsync( - string loginProvider, - string providerKey, + string loginProvider, + string providerKey, bool includeDetails = true, CancellationToken cancellationToken = default) { @@ -71,7 +71,7 @@ namespace Volo.Abp.Identity.MongoDB } public virtual async Task> GetListByNormalizedRoleNameAsync( - string normalizedRoleName, + string normalizedRoleName, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -89,9 +89,9 @@ namespace Volo.Abp.Identity.MongoDB public virtual async Task> GetListAsync( string sorting = null, - int maxResultCount = int.MaxValue, - int skipCount = 0, - string filter = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -100,7 +100,8 @@ namespace Volo.Abp.Identity.MongoDB !filter.IsNullOrWhiteSpace(), u => u.UserName.Contains(filter) || - u.Email.Contains(filter) + u.Email.Contains(filter) || + (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) ) .OrderBy(sorting ?? nameof(IdentityUser.UserName)) .As>() @@ -132,4 +133,4 @@ namespace Volo.Abp.Identity.MongoDB .LongCountAsync(GetCancellationToken(cancellationToken)); } } -} \ No newline at end of file +} diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj index 4c70886aaa..fa83d6c25e 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj @@ -3,7 +3,7 @@ - netcoreapp3.1 + netstandard2.0 MyCompanyName.MyProjectName diff --git a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj index 1466849524..4fb9f73c33 100644 --- a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj +++ b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Client/MyCompanyName.MyProjectName.HttpApi.Client.csproj @@ -3,7 +3,7 @@ - netcoreapp3.1 + netstandard2.0 MyCompanyName.MyProjectName