diff --git a/src/Umbraco.Core/Constants-PropertyEditors.cs b/src/Umbraco.Core/Constants-PropertyEditors.cs index a719e845b1..1a1eda2ae2 100644 --- a/src/Umbraco.Core/Constants-PropertyEditors.cs +++ b/src/Umbraco.Core/Constants-PropertyEditors.cs @@ -158,6 +158,11 @@ namespace Umbraco.Core /// public const string IntegerAlias = "Umbraco.Integer"; + /// + /// Alias for the Decimal datatype. + /// + public const string DecimalAlias = "Umbraco.Decimal"; + /// /// Alias for the listview datatype. /// diff --git a/src/Umbraco.Core/CoreBootManager.cs b/src/Umbraco.Core/CoreBootManager.cs index b4e3d06273..49829513bb 100644 --- a/src/Umbraco.Core/CoreBootManager.cs +++ b/src/Umbraco.Core/CoreBootManager.cs @@ -431,6 +431,7 @@ namespace Umbraco.Core new Lazy(() => typeof (DelimitedManifestValueValidator)), new Lazy(() => typeof (EmailValidator)), new Lazy(() => typeof (IntegerValidator)), + new Lazy(() => typeof (DecimalValidator)), }); //by default we'll use the db server registrar unless the developer has the legacy diff --git a/src/Umbraco.Core/Models/DataTypeDatabaseType.cs b/src/Umbraco.Core/Models/DataTypeDatabaseType.cs index e45cdd1a73..1db8ac65cb 100644 --- a/src/Umbraco.Core/Models/DataTypeDatabaseType.cs +++ b/src/Umbraco.Core/Models/DataTypeDatabaseType.cs @@ -21,6 +21,8 @@ namespace Umbraco.Core.Models [EnumMember] Integer, [EnumMember] - Date + Date, + [EnumMember] + Decimal } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs index 239792bf08..69c714c85a 100644 --- a/src/Umbraco.Core/Models/PropertyType.cs +++ b/src/Umbraco.Core/Models/PropertyType.cs @@ -402,6 +402,9 @@ namespace Umbraco.Core.Models if (DataTypeDatabaseType == DataTypeDatabaseType.Integer && type == typeof(int)) return true; + if (DataTypeDatabaseType == DataTypeDatabaseType.Decimal && type == typeof(decimal)) + return true; + if (DataTypeDatabaseType == DataTypeDatabaseType.Date && type == typeof(DateTime)) return true; diff --git a/src/Umbraco.Core/Models/Rdbms/PropertyDataDto.cs b/src/Umbraco.Core/Models/Rdbms/PropertyDataDto.cs index 4e59f0275b..63e3104d12 100644 --- a/src/Umbraco.Core/Models/Rdbms/PropertyDataDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/PropertyDataDto.cs @@ -33,6 +33,10 @@ namespace Umbraco.Core.Models.Rdbms [NullSetting(NullSetting = NullSettings.Null)] public int? Integer { get; set; } + [Column("dataDecimal")] + [NullSetting(NullSetting = NullSettings.Null)] + public decimal? Decimal { get; set; } + [Column("dataDate")] [NullSetting(NullSetting = NullSettings.Null)] public DateTime? Date { get; set; } @@ -55,22 +59,27 @@ namespace Umbraco.Core.Models.Rdbms { get { - if(Integer.HasValue) + if (Integer.HasValue) { return Integer.Value; } + + if (Decimal.HasValue) + { + return Decimal.Value; + } - if(Date.HasValue) + if (Date.HasValue) { return Date.Value; } - if(string.IsNullOrEmpty(VarChar) == false) + if (string.IsNullOrEmpty(VarChar) == false) { return VarChar; } - if(string.IsNullOrEmpty(Text) == false) + if (string.IsNullOrEmpty(Text) == false) { return Text; } diff --git a/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs b/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs index 4e3653bf9e..8d51b627ea 100644 --- a/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs @@ -63,7 +63,9 @@ namespace Umbraco.Core.Persistence.Factories //Check if property has an Id and set it, so that it can be updated if it already exists if (property.HasIdentity) + { dto.Id = property.Id; + } if (property.DataTypeDatabaseType == DataTypeDatabaseType.Integer) { @@ -82,11 +84,21 @@ namespace Umbraco.Core.Persistence.Factories } } } + else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Decimal && property.Value != null) + { + decimal val; + if (decimal.TryParse(property.Value.ToString(), out val)) + { + dto.Decimal = val; + } + } else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Date && property.Value != null && string.IsNullOrWhiteSpace(property.Value.ToString()) == false) { DateTime date; - if(DateTime.TryParse(property.Value.ToString(), out date)) + if (DateTime.TryParse(property.Value.ToString(), out date)) + { dto.Date = date; + } } else if (property.DataTypeDatabaseType == DataTypeDatabaseType.Ntext && property.Value != null) { diff --git a/src/Umbraco.Core/PropertyEditors/DecimalValidator.cs b/src/Umbraco.Core/PropertyEditors/DecimalValidator.cs new file mode 100644 index 0000000000..632821bc24 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/DecimalValidator.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using Umbraco.Core.Models; + +namespace Umbraco.Core.PropertyEditors +{ + /// + /// A validator that validates that the value is a valid decimal + /// + [ValueValidator("Decimal")] + internal sealed class DecimalValidator : ManifestValueValidator, IPropertyValidator + { + public override IEnumerable Validate(object value, string config, PreValueCollection preValues, PropertyEditor editor) + { + if (value != null && value.ToString() != string.Empty) + { + var result = value.TryConvertTo(); + if (result.Success == false) + { + yield return new ValidationResult("The value " + value + " is not a valid decimal", new[] { "value" }); + } + } + } + + public IEnumerable Validate(object value, PreValueCollection preValues, PropertyEditor editor) + { + return Validate(value, "", preValues, editor); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs index 8b00164059..3ddc557693 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs @@ -133,6 +133,8 @@ namespace Umbraco.Core.PropertyEditors case "INT": case "INTEGER": return DataTypeDatabaseType.Integer; + case "DECIMAL": + return DataTypeDatabaseType.Decimal; case "STRING": return DataTypeDatabaseType.Nvarchar; case "TEXT": @@ -202,6 +204,11 @@ namespace Umbraco.Core.PropertyEditors ? Attempt.Succeed((int)(long)result.Result) : result; + case DataTypeDatabaseType.Decimal: + //ensure these are nullable so we can return a null if required + valueType = typeof(decimal?); + break; + case DataTypeDatabaseType.Date: //ensure these are nullable so we can return a null if required valueType = typeof(DateTime?); @@ -283,6 +290,7 @@ namespace Umbraco.Core.PropertyEditors } return property.Value.ToString(); case DataTypeDatabaseType.Integer: + case DataTypeDatabaseType.Decimal: //we can just ToString() any of these types return property.Value.ToString(); case DataTypeDatabaseType.Date: @@ -325,6 +333,7 @@ namespace Umbraco.Core.PropertyEditors { case DataTypeDatabaseType.Date: case DataTypeDatabaseType.Integer: + case DataTypeDatabaseType.Decimal: return new XText(ConvertDbToString(property, propertyType, dataTypeService)); case DataTypeDatabaseType.Nvarchar: case DataTypeDatabaseType.Ntext: @@ -354,6 +363,7 @@ namespace Umbraco.Core.PropertyEditors property.Value.ToXmlString(); return property.Value.ToXmlString(); case DataTypeDatabaseType.Integer: + case DataTypeDatabaseType.Decimal: return property.Value.ToXmlString(property.Value.GetType()); case DataTypeDatabaseType.Date: //treat dates differently, output the format as xml format diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DecimalValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DecimalValueConverter.cs new file mode 100644 index 0000000000..32fe356764 --- /dev/null +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/DecimalValueConverter.cs @@ -0,0 +1,31 @@ +using Umbraco.Core.Models.PublishedContent; + +namespace Umbraco.Core.PropertyEditors.ValueConverters +{ + [PropertyValueType(typeof(decimal))] + [PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)] + public class DecimalValueConverter : PropertyValueConverterBase + { + public override bool IsConverter(PublishedPropertyType propertyType) + { + return Constants.PropertyEditors.DecimalAlias.Equals(propertyType.PropertyEditorAlias); + } + + public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview) + { + if (source == null) return 0M; + + // in XML a decimal is a string + var sourceString = source as string; + if (sourceString != null) + { + decimal d; + return (decimal.TryParse(sourceString, out d)) ? d : 0M; + } + + // in the database an a decimal is an a decimal + // default value is zero + return (source is decimal) ? source : 0M; + } + } +} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 15e00bcb8f..ae3ca88db1 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -456,7 +456,9 @@ + + diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/decimal.html b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/decimal.html new file mode 100644 index 0000000000..c4e4c95e39 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/decimal.html @@ -0,0 +1,11 @@ +
+ + + Not a number + {{propertyForm.requiredField.errorMsg}} + +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/number.html b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/number.html index 6d7b8c4c78..e7490e2703 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/number.html +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/number.html @@ -3,7 +3,7 @@ type="number" ng-model="model.value" val-server="value" - fix-number /> + fix-number /> Not a number {{propertyForm.requiredField.errorMsg}} diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/decimal/decimal.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/decimal/decimal.html new file mode 100644 index 0000000000..823a7b40ad --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/decimal/decimal.html @@ -0,0 +1,9 @@ +
+ + + Not a number + {{propertyForm.requiredField.errorMsg}} +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/integer/integer.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/integer/integer.html index 251a6066d8..28a81b035f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/integer/integer.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/integer/integer.html @@ -6,5 +6,4 @@ Not a number {{propertyForm.requiredField.errorMsg}} - \ No newline at end of file diff --git a/src/Umbraco.Web/PropertyEditors/DecimalPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DecimalPropertyEditor.cs new file mode 100644 index 0000000000..f636e8cdb2 --- /dev/null +++ b/src/Umbraco.Web/PropertyEditors/DecimalPropertyEditor.cs @@ -0,0 +1,57 @@ +using Umbraco.Core; +using Umbraco.Core.PropertyEditors; + +namespace Umbraco.Web.PropertyEditors +{ + [PropertyEditor(Constants.PropertyEditors.DecimalAlias, "Decimal", "decimal", "decimal", IsParameterEditor = true)] + public class DecimalPropertyEditor : PropertyEditor + { + /// + /// Overridden to ensure that the value is validated + /// + /// + protected override PropertyValueEditor CreateValueEditor() + { + var editor = base.CreateValueEditor(); + editor.Validators.Add(new DecimalValidator()); + return editor; + } + + protected override PreValueEditor CreatePreValueEditor() + { + return new DecimalPreValueEditor(); + } + + /// + /// A custom pre-value editor class to deal with the legacy way that the pre-value data is stored. + /// + internal class DecimalPreValueEditor : PreValueEditor + { + public DecimalPreValueEditor() + { + //create the fields + Fields.Add(new PreValueField(new DecimalValidator()) + { + Description = "Enter the minimum amount of number to be entered", + Key = "min", + View = "decimal", + Name = "Minimum" + }); + Fields.Add(new PreValueField(new DecimalValidator()) + { + Description = "Enter the intervals amount between each step of number to be entered", + Key = "step", + View = "decimal", + Name = "Step Size" + }); + Fields.Add(new PreValueField(new DecimalValidator()) + { + Description = "Enter the maximum amount of number to be entered", + Key = "max", + View = "decimal", + Name = "Maximum" + }); + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index f8744e58c2..07c378714b 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -307,6 +307,7 @@ +