Added custom validation messages to property types: model, dto and migration, update via property type editing, display when content editing.
This commit is contained in:
@@ -176,6 +176,7 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
To<ConvertTinyMceAndGridMediaUrlsToLocalLink>("{B69B6E8C-A769-4044-A27E-4A4E18D1645A}");
|
||||
To<RenameUserLoginDtoDateIndex>("{0372A42B-DECF-498D-B4D1-6379E907EB94}");
|
||||
To<FixContentNuCascade>("{5B1E0D93-F5A3-449B-84BA-65366B84E2D4}");
|
||||
To<AddPropertyTypeValidationMessageColumns>("{3D67D2C8-5E65-47D0-A9E1-DC2EE0779D6B}");
|
||||
|
||||
//FINAL
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_1_0
|
||||
{
|
||||
public class AddPropertyTypeValidationMessageColumns : MigrationBase
|
||||
{
|
||||
public AddPropertyTypeValidationMessageColumns(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToList();
|
||||
|
||||
AddColumnIfNotExists<PropertyTypeDto>(columns, "mandatoryMessage");
|
||||
AddColumnIfNotExists<PropertyTypeDto>(columns, "validationRegExpMessage");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,8 +25,10 @@ namespace Umbraco.Core.Models
|
||||
private string _propertyEditorAlias;
|
||||
private ValueStorageType _valueStorageType;
|
||||
private bool _mandatory;
|
||||
private string _mandatoryMessage;
|
||||
private int _sortOrder;
|
||||
private string _validationRegExp;
|
||||
private string _validationRegExpMessage;
|
||||
private ContentVariation _variations;
|
||||
|
||||
/// <summary>
|
||||
@@ -175,7 +177,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets of sets a value indicating whether a value for this property type is required.
|
||||
/// Gets or sets a value indicating whether a value for this property type is required.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public bool Mandatory
|
||||
@@ -184,6 +186,16 @@ namespace Umbraco.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _mandatory, nameof(Mandatory));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the custom validation message used when a value for this PropertyType is required
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string MandatoryMessage
|
||||
{
|
||||
get => _mandatoryMessage;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _mandatoryMessage, nameof(MandatoryMessage));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets of sets the sort order of the property type.
|
||||
/// </summary>
|
||||
@@ -204,6 +216,16 @@ namespace Umbraco.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _validationRegExp, nameof(ValidationRegExp));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the custom validation message used when a pattern for this PropertyType must be matched
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string ValidationRegExpMessage
|
||||
{
|
||||
get => _validationRegExpMessage;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _validationRegExpMessage, nameof(ValidationRegExpMessage));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content variation of the property type.
|
||||
/// </summary>
|
||||
|
||||
@@ -749,7 +749,9 @@ namespace Umbraco.Core.Packaging
|
||||
Name = property.Element("Name").Value,
|
||||
Description = (string)property.Element("Description"),
|
||||
Mandatory = property.Element("Mandatory") != null ? property.Element("Mandatory").Value.ToLowerInvariant().Equals("true") : false,
|
||||
MandatoryMessage = property.Element("MandatoryMessage") != null ? (string)property.Element("MandatoryMessage") : string.Empty,
|
||||
ValidationRegExp = (string)property.Element("Validation"),
|
||||
ValidationRegExpMessage = property.Element("ValidationRegExpMessage") != null ? (string)property.Element("ValidationRegExpMessage") : string.Empty,
|
||||
SortOrder = sortOrder
|
||||
};
|
||||
|
||||
|
||||
@@ -43,10 +43,20 @@ namespace Umbraco.Core.Persistence.Dtos
|
||||
[Constraint(Default = "0")]
|
||||
public bool Mandatory { get; set; }
|
||||
|
||||
[Column("mandatoryMessage")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(500)]
|
||||
public string MandatoryMessage { get; set; }
|
||||
|
||||
[Column("validationRegExp")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public string ValidationRegExp { get; set; }
|
||||
|
||||
[Column("validationRegExpMessage")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(500)]
|
||||
public string ValidationRegExpMessage { get; set; }
|
||||
|
||||
[Column("Description")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(2000)]
|
||||
|
||||
@@ -32,9 +32,15 @@ namespace Umbraco.Core.Persistence.Dtos
|
||||
[Column("mandatory")]
|
||||
public bool Mandatory { get; set; }
|
||||
|
||||
[Column("mandatoryMessage")]
|
||||
public string MandatoryMessage { get; set; }
|
||||
|
||||
[Column("validationRegExp")]
|
||||
public string ValidationRegExp { get; set; }
|
||||
|
||||
[Column("validationRegExpMessage")]
|
||||
public string ValidationRegExpMessage { get; set; }
|
||||
|
||||
[Column("Description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
|
||||
@@ -59,8 +59,10 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
propertyType.Key = typeDto.UniqueId;
|
||||
propertyType.Name = typeDto.Name;
|
||||
propertyType.Mandatory = typeDto.Mandatory;
|
||||
propertyType.MandatoryMessage = typeDto.MandatoryMessage;
|
||||
propertyType.SortOrder = typeDto.SortOrder;
|
||||
propertyType.ValidationRegExp = typeDto.ValidationRegExp;
|
||||
propertyType.ValidationRegExpMessage = typeDto.ValidationRegExpMessage;
|
||||
propertyType.PropertyGroupId = new Lazy<int>(() => tempGroupDto.Id);
|
||||
propertyType.CreateDate = createDate;
|
||||
propertyType.UpdateDate = updateDate;
|
||||
@@ -123,9 +125,11 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
DataTypeId = propertyType.DataTypeId,
|
||||
Description = propertyType.Description,
|
||||
Mandatory = propertyType.Mandatory,
|
||||
MandatoryMessage = propertyType.MandatoryMessage,
|
||||
Name = propertyType.Name,
|
||||
SortOrder = propertyType.SortOrder,
|
||||
ValidationRegExp = propertyType.ValidationRegExp,
|
||||
ValidationRegExpMessage = propertyType.ValidationRegExpMessage,
|
||||
UniqueId = propertyType.Key,
|
||||
Variations = (byte)propertyType.Variations
|
||||
};
|
||||
|
||||
@@ -24,9 +24,11 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.DataTypeId), nameof(PropertyTypeDto.DataTypeId));
|
||||
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.Description), nameof(PropertyTypeDto.Description));
|
||||
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.Mandatory), nameof(PropertyTypeDto.Mandatory));
|
||||
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.MandatoryMessage), nameof(PropertyTypeDto.MandatoryMessage));
|
||||
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.Name), nameof(PropertyTypeDto.Name));
|
||||
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.SortOrder), nameof(PropertyTypeDto.SortOrder));
|
||||
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.ValidationRegExp), nameof(PropertyTypeDto.ValidationRegExp));
|
||||
DefineMap<PropertyType, PropertyTypeDto>(nameof(PropertyType.ValidationRegExpMessage), nameof(PropertyTypeDto.ValidationRegExpMessage));
|
||||
DefineMap<PropertyType, DataTypeDto>(nameof(PropertyType.PropertyEditorAlias), nameof(DataTypeDto.EditorAlias));
|
||||
DefineMap<PropertyType, DataTypeDto>(nameof(PropertyType.ValueStorageType), nameof(DataTypeDto.DbType));
|
||||
}
|
||||
|
||||
@@ -293,10 +293,12 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
Id = dto.Id,
|
||||
Key = dto.UniqueId,
|
||||
Mandatory = dto.Mandatory,
|
||||
MandatoryMessage = dto.MandatoryMessage,
|
||||
Name = dto.Name,
|
||||
PropertyGroupId = groupId.HasValue ? new Lazy<int>(() => groupId.Value) : null,
|
||||
SortOrder = dto.SortOrder,
|
||||
ValidationRegExp = dto.ValidationRegExp,
|
||||
ValidationRegExpMessage = dto.ValidationRegExpMessage,
|
||||
Variations = (ContentVariation)dto.Variations
|
||||
};
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace Umbraco.Core.PropertyEditors
|
||||
public string ValueType { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<ValidationResult> Validate(object value, bool required, string format)
|
||||
public IEnumerable<ValidationResult> Validate(object value, bool required, string requiredMessage, string format, string formatMessage)
|
||||
{
|
||||
List<ValidationResult> results = null;
|
||||
var r = Validators.SelectMany(v => v.Validate(value, ValueType, Configuration)).ToList();
|
||||
@@ -97,14 +97,14 @@ namespace Umbraco.Core.PropertyEditors
|
||||
|
||||
if (required)
|
||||
{
|
||||
r = RequiredValidator.ValidateRequired(value, ValueType).ToList();
|
||||
r = RequiredValidator.ValidateRequired(value, ValueType, requiredMessage).ToList();
|
||||
if (r.Any()) { if (results == null) results = r; else results.AddRange(r); }
|
||||
}
|
||||
|
||||
var stringValue = value?.ToString();
|
||||
if (!string.IsNullOrWhiteSpace(format) && !string.IsNullOrWhiteSpace(stringValue))
|
||||
{
|
||||
r = FormatValidator.ValidateFormat(value, ValueType, format).ToList();
|
||||
r = FormatValidator.ValidateFormat(value, ValueType, format, formatMessage).ToList();
|
||||
if (r.Any()) { if (results == null) results = r; else results.AddRange(r); }
|
||||
}
|
||||
|
||||
|
||||
@@ -35,12 +35,14 @@ namespace Umbraco.Core.PropertyEditors
|
||||
bool HideLabel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Validates a property value.
|
||||
/// Validates a property value using custom messages.
|
||||
/// </summary>
|
||||
/// <param name="value">The property value.</param>
|
||||
/// <param name="required">A value indicating whether the property value is required.</param>
|
||||
/// <param name="requiredMessage">A custom validation message to use when the property value is required.</param>
|
||||
/// <param name="format">A specific format (regex) that the property value must respect.</param>
|
||||
IEnumerable<ValidationResult> Validate(object value, bool required, string format);
|
||||
/// <param name="formatMessage">A custom validation message to use when the property value is does not match the specific format (regex).</param>
|
||||
IEnumerable<ValidationResult> Validate(object value, bool required, string requiredMessage, string format, string formatMessage);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the validators to use to validate the edited value.
|
||||
|
||||
@@ -14,11 +14,12 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// <param name="value">The value to validate.</param>
|
||||
/// <param name="valueType">The value type.</param>
|
||||
/// <param name="format">A format definition.</param>
|
||||
/// <param name="formatMessage">A custom validation message to use when the property value is does not match the specific format (regex).</param>
|
||||
/// <returns>Validation results.</returns>
|
||||
/// <remarks>
|
||||
/// <para>The <paramref name="format" /> is expected to be a valid regular expression.</para>
|
||||
/// <para>This is used to validate values against the property type validation regular expression.</para>
|
||||
/// </remarks>
|
||||
IEnumerable<ValidationResult> ValidateFormat(object value, string valueType, string format);
|
||||
IEnumerable<ValidationResult> ValidateFormat(object value, string valueType, string format, string formatMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,11 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// </summary>
|
||||
/// <param name="value">The value to validate.</param>
|
||||
/// <param name="valueType">The value type.</param>
|
||||
/// <param name="requiredMessage">A custom validation message to use when the property value is required.</param>
|
||||
/// <returns>Validation results.</returns>
|
||||
/// <remarks>
|
||||
/// <para>This is used to validate values when the property type specifies that a value is required.</para>
|
||||
/// </remarks>
|
||||
IEnumerable<ValidationResult> ValidateRequired(object value, string valueType);
|
||||
IEnumerable<ValidationResult> ValidateRequired(object value, string valueType, string requiredMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,17 +58,28 @@ namespace Umbraco.Core.PropertyEditors.Validators
|
||||
public IEnumerable<ValidationResult> Validate(object value, string valueType, object dataTypeConfiguration)
|
||||
{
|
||||
if (_regex == null)
|
||||
{
|
||||
throw new InvalidOperationException("The validator has not been configured.");
|
||||
}
|
||||
|
||||
return ValidateFormat(value, valueType, _regex);
|
||||
return ValidateFormat(value, valueType, _regex, string.Empty);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IValueFormatValidator.ValidateFormat"/>
|
||||
public IEnumerable<ValidationResult> ValidateFormat(object value, string valueType, string format)
|
||||
public IEnumerable<ValidationResult> ValidateFormat(object value, string valueType, string format, string formatMessage)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(format)) throw new ArgumentNullOrEmptyException(nameof(format));
|
||||
if (string.IsNullOrWhiteSpace(format))
|
||||
{
|
||||
throw new ArgumentNullOrEmptyException(nameof(format));
|
||||
}
|
||||
|
||||
if (value == null || !new Regex(format).IsMatch(value.ToString()))
|
||||
yield return new ValidationResult(_textService.Localize("validation", "invalidPattern"), new[] { "value" });
|
||||
{
|
||||
var message = string.IsNullOrWhiteSpace(formatMessage)
|
||||
? _textService.Localize("validation", "invalidPattern")
|
||||
: formatMessage;
|
||||
yield return new ValidationResult(message, new[] { "value" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,28 +27,40 @@ namespace Umbraco.Core.PropertyEditors.Validators
|
||||
/// <inheritdoc cref="IValueValidator.Validate"/>
|
||||
public IEnumerable<ValidationResult> Validate(object value, string valueType, object dataTypeConfiguration)
|
||||
{
|
||||
return ValidateRequired(value, valueType);
|
||||
return ValidateRequired(value, valueType, string.Empty);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IValueRequiredValidator.ValidateRequired"/>
|
||||
public IEnumerable<ValidationResult> ValidateRequired(object value, string valueType)
|
||||
public IEnumerable<ValidationResult> ValidateRequired(object value, string valueType, string requiredMessage)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
yield return new ValidationResult(_textService.Localize("validation", "invalidNull"), new[] {"value"});
|
||||
var message = string.IsNullOrWhiteSpace(requiredMessage)
|
||||
? _textService.Localize("validation", "invalidNull")
|
||||
: requiredMessage;
|
||||
yield return new ValidationResult(message, new[] {"value"});
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (valueType.InvariantEquals(ValueTypes.Json))
|
||||
{
|
||||
var message = string.IsNullOrWhiteSpace(requiredMessage)
|
||||
? _textService.Localize("validation", "invalidEmpty")
|
||||
: requiredMessage;
|
||||
if (value.ToString().DetectIsEmptyJson())
|
||||
yield return new ValidationResult(_textService.Localize("validation", "invalidEmpty"), new[] { "value" });
|
||||
{
|
||||
yield return new ValidationResult(message, new[] { "value" });
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (value.ToString().IsNullOrWhiteSpace())
|
||||
{
|
||||
yield return new ValidationResult(_textService.Localize("validation", "invalidEmpty"), new[] { "value" });
|
||||
var message = string.IsNullOrWhiteSpace(requiredMessage)
|
||||
? _textService.Localize("validation", "invalidEmpty")
|
||||
: requiredMessage;
|
||||
yield return new ValidationResult(message, new[] { "value" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,7 +360,9 @@ namespace Umbraco.Core.Services.Implement
|
||||
new XElement("Definition", definition.Key),
|
||||
new XElement("Tab", propertyGroup == null ? "" : propertyGroup.Name),
|
||||
new XElement("Mandatory", propertyType.Mandatory.ToString()),
|
||||
new XElement("MandatoryMessage", propertyType.MandatoryMessage),
|
||||
new XElement("Validation", propertyType.ValidationRegExp),
|
||||
new XElement("ValidationRegExpMessage", propertyType.ValidationRegExpMessage),
|
||||
new XElement("Description", new XCData(propertyType.Description)));
|
||||
genericProperties.Add(genericProperty);
|
||||
}
|
||||
@@ -486,7 +488,9 @@ namespace Umbraco.Core.Services.Implement
|
||||
new XElement("Tab", propertyGroup == null ? "" : propertyGroup.Name),
|
||||
new XElement("SortOrder", propertyType.SortOrder),
|
||||
new XElement("Mandatory", propertyType.Mandatory.ToString()),
|
||||
propertyType.MandatoryMessage != null ? new XElement("MandatoryMessage", propertyType.MandatoryMessage) : null,
|
||||
propertyType.ValidationRegExp != null ? new XElement("Validation", propertyType.ValidationRegExp) : null,
|
||||
propertyType.ValidationRegExpMessage != null ? new XElement("ValidationRegExpMessage", propertyType.ValidationRegExpMessage) : null,
|
||||
propertyType.Description != null ? new XElement("Description", new XCData(propertyType.Description)) : null);
|
||||
|
||||
genericProperties.Add(genericProperty);
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace Umbraco.Core.Services
|
||||
var editor = _propertyEditors[propertyType.PropertyEditorAlias];
|
||||
var configuration = _dataTypeService.GetDataType(propertyType.DataTypeId).Configuration;
|
||||
var valueEditor = editor.GetValueEditor(configuration);
|
||||
return !valueEditor.Validate(value, propertyType.Mandatory, propertyType.ValidationRegExp).Any();
|
||||
return !valueEditor.Validate(value, propertyType.Mandatory, propertyType.MandatoryMessage, propertyType.ValidationRegExp, propertyType.ValidationRegExpMessage).Any();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +240,7 @@
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\RenameMediaVersionTable.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypes\ValueListPreValueMigrator.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypes\UmbracoSliderPreValueMigrator.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_1_0\AddPropertyTypeValidationMessageColumns.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_1_0\FixContentNuCascade.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_1_0\RenameUserLoginDtoDateIndex.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_1\ChangeNuCacheJsonFormat.cs" />
|
||||
|
||||
@@ -621,7 +621,9 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Validation = new PropertyTypeValidation()
|
||||
{
|
||||
Mandatory = true,
|
||||
Pattern = "xyz"
|
||||
MandatoryMessage = "Please enter a value",
|
||||
Pattern = "xyz",
|
||||
PatternMessage = "Please match the pattern",
|
||||
}
|
||||
};
|
||||
|
||||
@@ -634,7 +636,9 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Assert.AreEqual(basic.DataTypeId, result.DataTypeId);
|
||||
Assert.AreEqual(basic.Label, result.Name);
|
||||
Assert.AreEqual(basic.Validation.Mandatory, result.Mandatory);
|
||||
Assert.AreEqual(basic.Validation.MandatoryMessage, result.MandatoryMessage);
|
||||
Assert.AreEqual(basic.Validation.Pattern, result.ValidationRegExp);
|
||||
Assert.AreEqual(basic.Validation.PatternMessage, result.ValidationRegExpMessage);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -655,7 +659,9 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Validation = new PropertyTypeValidation()
|
||||
{
|
||||
Mandatory = true,
|
||||
Pattern = "xyz"
|
||||
MandatoryMessage = "Please enter a value",
|
||||
Pattern = "xyz",
|
||||
PatternMessage = "Please match the pattern",
|
||||
}
|
||||
};
|
||||
|
||||
@@ -668,7 +674,9 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Assert.AreEqual(basic.DataTypeId, result.DataTypeId);
|
||||
Assert.AreEqual(basic.Label, result.Name);
|
||||
Assert.AreEqual(basic.Validation.Mandatory, result.Mandatory);
|
||||
Assert.AreEqual(basic.Validation.MandatoryMessage, result.MandatoryMessage);
|
||||
Assert.AreEqual(basic.Validation.Pattern, result.ValidationRegExp);
|
||||
Assert.AreEqual(basic.Validation.PatternMessage, result.ValidationRegExpMessage);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -951,7 +959,7 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Name = "Tab 1",
|
||||
SortOrder = 0,
|
||||
Inherited = false,
|
||||
Properties = new []
|
||||
Properties = new[]
|
||||
{
|
||||
new MemberPropertyTypeBasic
|
||||
{
|
||||
@@ -965,7 +973,7 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Validation = new PropertyTypeValidation
|
||||
{
|
||||
Mandatory = false,
|
||||
Pattern = ""
|
||||
Pattern = string.Empty
|
||||
},
|
||||
SortOrder = 0,
|
||||
DataTypeId = 555
|
||||
@@ -1000,7 +1008,7 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Name = "Tab 1",
|
||||
SortOrder = 0,
|
||||
Inherited = false,
|
||||
Properties = new []
|
||||
Properties = new[]
|
||||
{
|
||||
new PropertyTypeBasic
|
||||
{
|
||||
@@ -1011,7 +1019,7 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Validation = new PropertyTypeValidation
|
||||
{
|
||||
Mandatory = false,
|
||||
Pattern = ""
|
||||
Pattern = string.Empty
|
||||
},
|
||||
SortOrder = 0,
|
||||
DataTypeId = 555
|
||||
@@ -1052,7 +1060,7 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Name = "Tab 1",
|
||||
SortOrder = 0,
|
||||
Inherited = false,
|
||||
Properties = new []
|
||||
Properties = new[]
|
||||
{
|
||||
new PropertyTypeBasic
|
||||
{
|
||||
@@ -1063,7 +1071,7 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Validation = new PropertyTypeValidation
|
||||
{
|
||||
Mandatory = false,
|
||||
Pattern = ""
|
||||
Pattern = string.Empty
|
||||
},
|
||||
SortOrder = 0,
|
||||
DataTypeId = 555
|
||||
@@ -1109,7 +1117,7 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Validation = new PropertyTypeValidation
|
||||
{
|
||||
Mandatory = false,
|
||||
Pattern = ""
|
||||
Pattern = string.Empty
|
||||
},
|
||||
SortOrder = 0,
|
||||
DataTypeId = 555
|
||||
@@ -1133,7 +1141,7 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Validation = new PropertyTypeValidation
|
||||
{
|
||||
Mandatory = false,
|
||||
Pattern = ""
|
||||
Pattern = string.Empty
|
||||
},
|
||||
SortOrder = 0,
|
||||
DataTypeId = 555
|
||||
@@ -1187,7 +1195,7 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Validation = new PropertyTypeValidation
|
||||
{
|
||||
Mandatory = false,
|
||||
Pattern = ""
|
||||
Pattern = string.Empty
|
||||
},
|
||||
SortOrder = 0,
|
||||
DataTypeId = 555
|
||||
@@ -1211,7 +1219,7 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Validation = new PropertyTypeValidation
|
||||
{
|
||||
Mandatory = false,
|
||||
Pattern = ""
|
||||
Pattern = string.Empty
|
||||
},
|
||||
SortOrder = 0,
|
||||
DataTypeId = 555
|
||||
|
||||
@@ -501,7 +501,9 @@
|
||||
property.dataTypeIcon = propertyModel.dataTypeIcon;
|
||||
property.dataTypeName = propertyModel.dataTypeName;
|
||||
property.validation.mandatory = propertyModel.validation.mandatory;
|
||||
property.validation.mandatoryMessage = propertyModel.validation.mandatoryMessage;
|
||||
property.validation.pattern = propertyModel.validation.pattern;
|
||||
property.validation.patternMessage = propertyModel.validation.patternMessage;
|
||||
property.showOnMemberProfile = propertyModel.showOnMemberProfile;
|
||||
property.memberCanEdit = propertyModel.memberCanEdit;
|
||||
property.isSensitiveValue = propertyModel.isSensitiveValue;
|
||||
@@ -592,7 +594,9 @@
|
||||
propertyState: "init",
|
||||
validation: {
|
||||
mandatory: false,
|
||||
pattern: null
|
||||
mandatoryMessage: null,
|
||||
pattern: null,
|
||||
patternMessage: null
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -494,11 +494,11 @@ input.umb-group-builder__group-sort-value {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
color: @ui-action-type;
|
||||
|
||||
&:hover{
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
color:@ui-action-type-hover;
|
||||
border-color:@ui-action-border-hover;
|
||||
color: @ui-action-type-hover;
|
||||
border-color: @ui-action-border-hover;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,7 +555,13 @@ input.umb-group-builder__group-sort-value {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.editor-validation-pattern{
|
||||
.editor-validation-message {
|
||||
min-width: 100%;
|
||||
min-height: 25px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.editor-validation-pattern {
|
||||
border: 1px solid @gray-7;
|
||||
margin: 10px 0 0;
|
||||
padding: 6px;
|
||||
|
||||
@@ -528,7 +528,8 @@ input[type="checkbox"][readonly] {
|
||||
.help-inline {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding-left: 5px;
|
||||
padding-top: 4px;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
div.help {
|
||||
|
||||
@@ -81,38 +81,55 @@
|
||||
</div>
|
||||
|
||||
<div class="umb-control-group clearfix" ng-if="!model.property.locked">
|
||||
|
||||
|
||||
<h5><localize key="validation_validation"></localize></h5>
|
||||
|
||||
<label>
|
||||
|
||||
<label>
|
||||
<localize key="validation_fieldIsMandatory"></localize>
|
||||
</label>
|
||||
|
||||
<umb-toggle data-element="validation_mandatory"
|
||||
checked="model.property.validation.mandatory"
|
||||
on-click="vm.toggleValidation()"
|
||||
>
|
||||
on-click="vm.toggleValidation()">
|
||||
</umb-toggle>
|
||||
|
||||
<label class="mt3">
|
||||
<textarea class="editor-validation-message"
|
||||
localize="placeholder"
|
||||
placeholder="@validation_mandatoryMessage"
|
||||
ng-model="model.property.validation.mandatoryMessage"
|
||||
ng-if="model.property.validation.mandatory"
|
||||
umb-auto-resize
|
||||
ng-keypress="vm.submitOnEnter($event)">
|
||||
</textarea>
|
||||
|
||||
<label class="mt3">
|
||||
<localize key="validation_customValidation"></localize>
|
||||
</label>
|
||||
|
||||
|
||||
<select class="umb-dropdown" ng-options="validationType.name for validationType in vm.validationTypes" ng-model="vm.selectedValidationType" ng-change="vm.changeValidationType(vm.selectedValidationType)">
|
||||
<option value=""><localize key="validation_noValidation">No validation</localize></option>
|
||||
</select>
|
||||
|
||||
|
||||
<textarea class="editor-validation-pattern"
|
||||
localize="placeholder"
|
||||
placeholder="@validation_validationRegExp"
|
||||
ng-model="model.property.validation.pattern"
|
||||
ng-change="vm.changeValidationPattern()"
|
||||
ng-if="vm.showValidationPattern"
|
||||
umb-auto-resize
|
||||
focus-when="{{vm.focusOnPatternField}}"
|
||||
ng-keypress="vm.submitOnEnter($event)">
|
||||
</textarea>
|
||||
|
||||
localize="placeholder"
|
||||
placeholder="@validation_validationRegExp"
|
||||
ng-model="model.property.validation.pattern"
|
||||
ng-change="vm.changeValidationPattern()"
|
||||
ng-if="vm.showValidationPattern"
|
||||
umb-auto-resize
|
||||
focus-when="{{vm.focusOnPatternField}}"
|
||||
ng-keypress="vm.submitOnEnter($event)">
|
||||
</textarea>
|
||||
|
||||
<textarea class="editor-validation-message"
|
||||
localize="placeholder"
|
||||
placeholder="@validation_validationRegExpMessage"
|
||||
ng-model="model.property.validation.patternMessage"
|
||||
ng-if="vm.showValidationPattern"
|
||||
umb-auto-resize
|
||||
ng-keypress="vm.submitOnEnter($event)">
|
||||
</textarea>
|
||||
|
||||
</div>
|
||||
<div class="umb-control-group clearfix" ng-if="model.contentType === 'documentType' && model.contentTypeAllowCultureVariant">
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function textboxController($scope) {
|
||||
function textboxController($scope, localizationService) {
|
||||
// macro parameter editor doesn't contains a config object,
|
||||
// so we create a new one to hold any properties
|
||||
if (!$scope.model.config) {
|
||||
@@ -18,6 +18,15 @@ function textboxController($scope) {
|
||||
}
|
||||
}
|
||||
$scope.model.change();
|
||||
|
||||
$scope.mandatoryMessage = "";
|
||||
if ($scope.model.validation.mandatoryMessage) {
|
||||
$scope.mandatoryMessage = $scope.model.validation.mandatoryMessage;
|
||||
} else {
|
||||
localizationService.localize("general_required").then(function (value) {
|
||||
$scope.mandatoryMessage = value;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
angular.module('umbraco').controller("Umbraco.PropertyEditors.textboxController", textboxController);
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
ng-trim="false"
|
||||
ng-keyup="model.change()" />
|
||||
|
||||
<span ng-messages="textboxFieldForm.textbox.$error" show-validation-on-submit >
|
||||
<span ng-messages="textboxFieldForm.textbox.$error" show-validation-on-submit>
|
||||
<span class="help-inline" ng-message="valServer">{{textboxFieldForm.textbox.errorMsg}}</span>
|
||||
<span class="help-inline" ng-message="required"><localize key="general_required">Required</localize></span>
|
||||
<span class="help-inline" ng-message="required">{{mandatoryMessage}}</span>
|
||||
</span>
|
||||
|
||||
<div class="help" ng-if="model.count >= (model.config.maxChars*.8) && model.count <= model.config.maxChars">
|
||||
|
||||
@@ -1951,7 +1951,9 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="validateAsUrl">Validate as a URL</key>
|
||||
<key alias="enterCustomValidation">...or enter a custom validation</key>
|
||||
<key alias="fieldIsMandatory">Field is mandatory</key>
|
||||
<key alias="mandatoryMessage">Enter a custom validation error message (optional)</key>
|
||||
<key alias="validationRegExp">Enter a regular expression</key>
|
||||
<key alias="validationRegExpMessage">Enter a custom validation error message (optional)</key>
|
||||
<key alias="minCount">You need to add at least</key>
|
||||
<key alias="maxCount">You can only have</key>
|
||||
<key alias="items">items</key>
|
||||
|
||||
@@ -1961,7 +1961,9 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="validateAsUrl">Validate as a URL</key>
|
||||
<key alias="enterCustomValidation">...or enter a custom validation</key>
|
||||
<key alias="fieldIsMandatory">Field is mandatory</key>
|
||||
<key alias="mandatoryMessage">Enter a custom validation error message (optional)</key>
|
||||
<key alias="validationRegExp">Enter a regular expression</key>
|
||||
<key alias="validationRegExpMessage">Enter a custom validation error message (optional)</key>
|
||||
<key alias="minCount">You need to add at least</key>
|
||||
<key alias="maxCount">You can only have</key>
|
||||
<key alias="items">items</key>
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace Umbraco.Web.Editors.Filters
|
||||
{
|
||||
// validate
|
||||
var valueEditor = editor.GetValueEditor(property.DataType.Configuration);
|
||||
foreach (var r in valueEditor.Validate(postedValue, property.IsRequired, property.ValidationRegExp))
|
||||
foreach (var r in valueEditor.Validate(postedValue, property.IsRequired, property.IsRequiredMessage, property.ValidationRegExp, property.ValidationRegExpMessage))
|
||||
{
|
||||
modelState.AddPropertyError(r, property.Alias, property.Culture);
|
||||
}
|
||||
|
||||
@@ -11,10 +11,17 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
internal class ContentPropertyDto : ContentPropertyBasic
|
||||
{
|
||||
public IDataType DataType { get; set; }
|
||||
|
||||
public string Label { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
|
||||
public bool IsRequired { get; set; }
|
||||
|
||||
public string IsRequiredMessage { get; set; }
|
||||
|
||||
public string ValidationRegExp { get; set; }
|
||||
|
||||
public string ValidationRegExpMessage { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,13 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
[DataMember(Name = "mandatory")]
|
||||
public bool Mandatory { get; set; }
|
||||
|
||||
[DataMember(Name = "mandatoryMessage")]
|
||||
public string MandatoryMessage { get; set; }
|
||||
|
||||
[DataMember(Name = "pattern")]
|
||||
public string Pattern { get; set; }
|
||||
|
||||
[DataMember(Name = "patternMessage")]
|
||||
public string PatternMessage { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,9 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
//add the validation information
|
||||
dest.Validation.Mandatory = originalProp.PropertyType.Mandatory;
|
||||
dest.Validation.MandatoryMessage = originalProp.PropertyType.MandatoryMessage;
|
||||
dest.Validation.Pattern = originalProp.PropertyType.ValidationRegExp;
|
||||
dest.Validation.PatternMessage = originalProp.PropertyType.ValidationRegExpMessage;
|
||||
|
||||
if (dest.PropertyEditor == null)
|
||||
{
|
||||
|
||||
@@ -21,7 +21,9 @@ namespace Umbraco.Web.Models.Mapping
|
||||
base.Map(property, dest, context);
|
||||
|
||||
dest.IsRequired = property.PropertyType.Mandatory;
|
||||
dest.IsRequiredMessage = property.PropertyType.MandatoryMessage;
|
||||
dest.ValidationRegExp = property.PropertyType.ValidationRegExp;
|
||||
dest.ValidationRegExpMessage = property.PropertyType.ValidationRegExpMessage;
|
||||
dest.Description = property.PropertyType.Description;
|
||||
dest.Label = property.PropertyType.Name;
|
||||
dest.DataType = DataTypeService.GetDataType(property.PropertyType.DataTypeId);
|
||||
|
||||
@@ -220,7 +220,9 @@ namespace Umbraco.Web.Models.Mapping
|
||||
target.Name = source.Label;
|
||||
target.DataTypeId = source.DataTypeId;
|
||||
target.Mandatory = source.Validation.Mandatory;
|
||||
target.MandatoryMessage = source.Validation.MandatoryMessage;
|
||||
target.ValidationRegExp = source.Validation.Pattern;
|
||||
target.ValidationRegExpMessage = source.Validation.PatternMessage;
|
||||
target.Variations = source.AllowCultureVariant ? ContentVariation.Culture : ContentVariation.Nothing;
|
||||
|
||||
if (source.Id > 0)
|
||||
|
||||
@@ -223,7 +223,13 @@ namespace Umbraco.Web.Models.Mapping
|
||||
Alias = p.Alias,
|
||||
Description = p.Description,
|
||||
Editor = p.PropertyEditorAlias,
|
||||
Validation = new PropertyTypeValidation {Mandatory = p.Mandatory, Pattern = p.ValidationRegExp},
|
||||
Validation = new PropertyTypeValidation
|
||||
{
|
||||
Mandatory = p.Mandatory,
|
||||
MandatoryMessage = p.MandatoryMessage,
|
||||
Pattern = p.ValidationRegExp,
|
||||
PatternMessage = p.ValidationRegExpMessage,
|
||||
},
|
||||
Label = p.Name,
|
||||
View = propertyEditor.GetValueEditor().View,
|
||||
Config = config,
|
||||
|
||||
@@ -313,9 +313,19 @@ namespace Umbraco.Web.PropertyEditors
|
||||
if (propType.Mandatory)
|
||||
{
|
||||
if (propValues[propKey] == null)
|
||||
yield return new ValidationResult("Item " + (i + 1) + " '" + propType.Name + "' cannot be null", new[] { propKey });
|
||||
{
|
||||
var message = string.IsNullOrWhiteSpace(propType.MandatoryMessage)
|
||||
? $"'{propType.Name}' cannot be null"
|
||||
: propType.MandatoryMessage;
|
||||
yield return new ValidationResult($"Item {(i + 1)}: {message}", new[] { propKey });
|
||||
}
|
||||
else if (propValues[propKey].ToString().IsNullOrWhiteSpace() || (propValues[propKey].Type == JTokenType.Array && !propValues[propKey].HasValues))
|
||||
yield return new ValidationResult("Item " + (i + 1) + " '" + propType.Name + "' cannot be empty", new[] { propKey });
|
||||
{
|
||||
var message = string.IsNullOrWhiteSpace(propType.MandatoryMessage)
|
||||
? $"'{propType.Name}' cannot be empty"
|
||||
: propType.MandatoryMessage;
|
||||
yield return new ValidationResult($"Item{(i + 1)}: {message}", new[] { propKey });
|
||||
}
|
||||
}
|
||||
|
||||
// Check regex
|
||||
@@ -325,7 +335,10 @@ namespace Umbraco.Web.PropertyEditors
|
||||
var regex = new Regex(propType.ValidationRegExp);
|
||||
if (!regex.IsMatch(propValues[propKey].ToString()))
|
||||
{
|
||||
yield return new ValidationResult("Item " + (i + 1) + " '" + propType.Name + "' is invalid, it does not match the correct pattern", new[] { propKey });
|
||||
var message = string.IsNullOrWhiteSpace(propType.ValidationRegExpMessage)
|
||||
? $"'{propType.Name}' is invalid, it does not match the correct pattern"
|
||||
: propType.ValidationRegExpMessage;
|
||||
yield return new ValidationResult($"Item {(i + 1)}: {message}", new[] { propKey });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
private class RequiredJsonValueValidator : IValueRequiredValidator
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<ValidationResult> ValidateRequired(object value, string valueType)
|
||||
public IEnumerable<ValidationResult> ValidateRequired(object value, string valueType, string requiredMessage)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user