Fixes property editors that have default pre-values for those prevalues to show up when creating a new data type, fixes: U4-3147 Create tag supported property editors - and adds the tag group to the pre-values for the tag property editor.
This commit is contained in:
@@ -8,9 +8,22 @@ namespace Umbraco.Core.PropertyEditors
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class SupportTagsAttribute : Attribute
|
||||
{
|
||||
//TODO: We should be able to add an overload to this to provide a 'tag definition' so developers can dynamically change
|
||||
// things like TagGroup and ReplaceTags at runtime.
|
||||
public Type TagPropertyDefinitionType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines a tag property definition type to invoke at runtime to get the tags configuration for a property
|
||||
/// </summary>
|
||||
/// <param name="tagPropertyDefinitionType"></param>
|
||||
public SupportTagsAttribute(Type tagPropertyDefinitionType)
|
||||
: this()
|
||||
{
|
||||
if (tagPropertyDefinitionType == null) throw new ArgumentNullException("tagPropertyDefinitionType");
|
||||
TagPropertyDefinitionType = tagPropertyDefinitionType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normal constructor specifying the default tags configuration for a property
|
||||
/// </summary>
|
||||
public SupportTagsAttribute()
|
||||
{
|
||||
ValueType = TagValueType.FromDelimitedValue;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using Umbraco.Core.Models.Editors;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows for dynamically changing how a property's data is tagged at runtime during property setting
|
||||
/// </summary>
|
||||
public abstract class TagPropertyDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// The property data that will create the tag data
|
||||
/// </summary>
|
||||
public ContentPropertyData PropertySaving { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The attribute that has specified this definition type
|
||||
/// </summary>
|
||||
public SupportTagsAttribute TagsAttribute { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor specifies the defaults and sets the ContentPropertyData being used to set the tag values which
|
||||
/// can be used to dynamically adjust the tags definition for this property.
|
||||
/// </summary>
|
||||
/// <param name="propertySaving"></param>
|
||||
/// <param name="tagsAttribute"></param>
|
||||
protected TagPropertyDefinition(ContentPropertyData propertySaving, SupportTagsAttribute tagsAttribute)
|
||||
{
|
||||
PropertySaving = propertySaving;
|
||||
TagsAttribute = tagsAttribute;
|
||||
Delimiter = tagsAttribute.Delimiter;
|
||||
ReplaceTags = tagsAttribute.ReplaceTags;
|
||||
TagGroup = tagsAttribute.TagGroup;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines a custom delimiter, the default is a comma
|
||||
/// </summary>
|
||||
public virtual string Delimiter { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether or not to replace the tags with the new value or append them (true to replace, false to append), default is true
|
||||
/// </summary>
|
||||
public virtual bool ReplaceTags { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The tag group to use when tagging, the default is 'default'
|
||||
/// </summary>
|
||||
public virtual string TagGroup { get; private set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -334,6 +334,7 @@
|
||||
<Compile Include="PropertyEditors\PropertyCacheLevel.cs" />
|
||||
<Compile Include="PropertyEditors\PropertyValueConverterBase.cs" />
|
||||
<Compile Include="PropertyEditors\SupportTagsAttribute.cs" />
|
||||
<Compile Include="PropertyEditors\TagPropertyDefinition.cs" />
|
||||
<Compile Include="PropertyEditors\TagValueType.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\IntegerValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\JsonValueConverter.cs" />
|
||||
|
||||
@@ -116,8 +116,8 @@ namespace Umbraco.Web.Editors
|
||||
var propVal = p.PropertyEditor.ValueEditor.ConvertEditorToDb(data, dboProperty.Value);
|
||||
var supportTagsAttribute = TagExtractor.GetAttribute(p.PropertyEditor);
|
||||
if (supportTagsAttribute != null)
|
||||
{
|
||||
TagExtractor.SetPropertyTags(contentItem.PersistedContent, dboProperty, propVal, supportTagsAttribute);
|
||||
{
|
||||
TagExtractor.SetPropertyTags(contentItem.PersistedContent, dboProperty, data, propVal, supportTagsAttribute);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Models.Mapping;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi.Binders;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
@@ -42,10 +43,6 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
//TODO: Here we need to do a legacy check... if we cannot find a property editor with the alias
|
||||
// we should display a warning but let them select a different one!
|
||||
|
||||
return Mapper.Map<IDataTypeDefinition, DataTypeDisplay>(dataType);
|
||||
}
|
||||
|
||||
@@ -62,8 +59,7 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Services.DataTypeService.Delete(foundType, UmbracoUser.Id);
|
||||
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
@@ -91,8 +87,8 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
if (dataTypeId == -1)
|
||||
{
|
||||
//this is a new data type, so just return the field editors, there are no values yet
|
||||
return propEd.PreValueEditor.Fields.Select(Mapper.Map<PreValueFieldDisplay>);
|
||||
//this is a new data type, so just return the field editors with default values
|
||||
return Mapper.Map<PropertyEditor, IEnumerable<PreValueFieldDisplay>>(propEd);
|
||||
}
|
||||
|
||||
//we have a data type associated
|
||||
@@ -111,8 +107,8 @@ namespace Umbraco.Web.Editors
|
||||
return Mapper.Map<IDataTypeDefinition, IEnumerable<PreValueFieldDisplay>>(dataType);
|
||||
}
|
||||
|
||||
//return the pre value display without values
|
||||
return propEd.PreValueEditor.Fields.Select(Mapper.Map<PreValueFieldDisplay>);
|
||||
//these are new pre-values, so just return the field editors with default values
|
||||
return Mapper.Map<PropertyEditor, IEnumerable<PreValueFieldDisplay>>(propEd);
|
||||
}
|
||||
|
||||
//TODO: Generally there probably won't be file uploads for pre-values but we should allow them just like we do for the content editor
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Editors;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
@@ -22,22 +24,47 @@ namespace Umbraco.Web.Editors
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="property"></param>
|
||||
/// <param name="propertyValue"></param>
|
||||
/// <param name="propertyData"></param>
|
||||
/// <param name="convertedPropertyValue"></param>
|
||||
/// <param name="attribute"></param>
|
||||
public static void SetPropertyTags(IContentBase content, Property property, object propertyValue, SupportTagsAttribute attribute)
|
||||
public static void SetPropertyTags(IContentBase content, Property property, ContentPropertyData propertyData, object convertedPropertyValue, SupportTagsAttribute attribute)
|
||||
{
|
||||
switch (attribute.ValueType)
|
||||
//check for a custom definition
|
||||
if (attribute.TagPropertyDefinitionType != null)
|
||||
{
|
||||
//try to create it
|
||||
TagPropertyDefinition def;
|
||||
try
|
||||
{
|
||||
def = (TagPropertyDefinition) Activator.CreateInstance(attribute.TagPropertyDefinitionType, propertyData, attribute);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<TagExtractor>("Could not create custom " + attribute.TagPropertyDefinitionType + " tag definition", ex);
|
||||
throw;
|
||||
}
|
||||
SetPropertyTags(content, property, convertedPropertyValue, def.Delimiter, def.ReplaceTags, def.TagGroup, attribute.ValueType);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetPropertyTags(content, property, convertedPropertyValue, attribute.Delimiter, attribute.ReplaceTags, attribute.TagGroup, attribute.ValueType);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetPropertyTags(IContentBase content, Property property, object convertedPropertyValue, string delimiter, bool replaceTags, string tagGroup, TagValueType valueType)
|
||||
{
|
||||
switch (valueType)
|
||||
{
|
||||
case TagValueType.FromDelimitedValue:
|
||||
var tags = propertyValue.ToString().Split(new[] { attribute.Delimiter }, StringSplitOptions.RemoveEmptyEntries);
|
||||
content.SetTags(property.Alias, tags, attribute.ReplaceTags, attribute.TagGroup);
|
||||
var tags = convertedPropertyValue.ToString().Split(new[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
|
||||
content.SetTags(property.Alias, tags, replaceTags, tagGroup);
|
||||
break;
|
||||
case TagValueType.CustomTagList:
|
||||
//for this to work the object value must be IENumerable<string>
|
||||
var stringList = propertyValue as IEnumerable<string>;
|
||||
var stringList = convertedPropertyValue as IEnumerable<string>;
|
||||
if (stringList != null)
|
||||
{
|
||||
content.SetTags(property.Alias, stringList, attribute.ReplaceTags, attribute.TagGroup);
|
||||
content.SetTags(property.Alias, stringList, replaceTags, tagGroup);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -39,8 +39,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
var resolver = new PreValueDisplayResolver(lazyDataTypeService);
|
||||
return resolver.Convert(definition);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
config.CreateMap<DataTypeSave, IDataTypeDefinition>()
|
||||
.ConstructUsing(save => new DataTypeDefinition(-1, save.SelectedEditor) {CreateDate = DateTime.Now})
|
||||
@@ -48,6 +47,20 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(definition => definition.PropertyEditorAlias, expression => expression.MapFrom(save => save.SelectedEditor))
|
||||
.ForMember(definition => definition.ParentId, expression => expression.MapFrom(save => -1))
|
||||
.ForMember(definition => definition.DatabaseType, expression => expression.ResolveUsing<DatabaseTypeResolver>());
|
||||
|
||||
//Converts a property editor to a new list of pre-value fields - used when creating a new data type or changing a data type with new pre-vals
|
||||
config.CreateMap<PropertyEditor, IEnumerable<PreValueFieldDisplay>>()
|
||||
.ConvertUsing(editor =>
|
||||
{
|
||||
//this is a new data type, so just return the field editors, there are no values yet
|
||||
var defaultVals = editor.DefaultPreValues;
|
||||
var fields = editor.PreValueEditor.Fields.Select(Mapper.Map<PreValueFieldDisplay>).ToArray();
|
||||
if (defaultVals != null)
|
||||
{
|
||||
PreValueDisplayResolver.MapPreValueValuesToPreValueFields(fields, defaultVals, true);
|
||||
}
|
||||
return fields;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,47 @@ namespace Umbraco.Web.Models.Mapping
|
||||
_dataTypeService = dataTypeService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps pre-values in the dictionary to the values for the fields
|
||||
/// </summary>
|
||||
/// <param name="fields"></param>
|
||||
/// <param name="preValues"></param>
|
||||
/// <param name="isDictionaryBased"></param>
|
||||
internal static void MapPreValueValuesToPreValueFields(PreValueFieldDisplay[] fields, IDictionary<string, object> preValues, bool isDictionaryBased)
|
||||
{
|
||||
if (fields == null) throw new ArgumentNullException("fields");
|
||||
if (preValues == null) throw new ArgumentNullException("preValues");
|
||||
//now we need to wire up the pre-values values with the actual fields defined
|
||||
var currentIndex = 0; //used if the collection is non-dictionary based.
|
||||
foreach (var field in fields)
|
||||
{
|
||||
if (isDictionaryBased == false)
|
||||
{
|
||||
//we'll just need to wire up the values based on the order that the pre-values are stored
|
||||
var found = preValues.Any(x => x.Key.InvariantEquals(currentIndex.ToInvariantString()));
|
||||
if (found == false)
|
||||
{
|
||||
LogHelper.Warn<PreValueDisplayResolver>("Could not find persisted pre-value for index " + currentIndex);
|
||||
continue;
|
||||
}
|
||||
field.Value = preValues.Single(x => x.Key.InvariantEquals(currentIndex.ToInvariantString())).Value.ToString();
|
||||
currentIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
var found = preValues.Any(x => x.Key.InvariantEquals(field.Key));
|
||||
if (found == false)
|
||||
{
|
||||
LogHelper.Warn<PreValueDisplayResolver>("Could not find persisted pre-value for field " + field.Key);
|
||||
continue;
|
||||
}
|
||||
field.Value = preValues.Single(x => x.Key.InvariantEquals(field.Key)).Value;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerable<PreValueFieldDisplay> Convert(IDataTypeDefinition source)
|
||||
{
|
||||
PropertyEditor propEd = null;
|
||||
@@ -45,36 +86,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
dictionaryVals = propEd.PreValueEditor.ConvertDbToEditor(propEd.DefaultPreValues, preVals);
|
||||
}
|
||||
|
||||
var currentIndex = 0; //used if the collection is non-dictionary based.
|
||||
|
||||
//now we need to wire up the pre-values values with the actual fields defined
|
||||
foreach (var field in result)
|
||||
{
|
||||
if (preVals.IsDictionaryBased == false)
|
||||
{
|
||||
//we'll just need to wire up the values based on the order that the pre-values are stored
|
||||
var found = dictionaryVals.Any(x => x.Key.InvariantEquals(currentIndex.ToInvariantString()));
|
||||
if (found == false)
|
||||
{
|
||||
LogHelper.Warn<PreValueDisplayResolver>("Could not find persisted pre-value for index " + currentIndex);
|
||||
continue;
|
||||
}
|
||||
field.Value = dictionaryVals.Single(x => x.Key.InvariantEquals(currentIndex.ToInvariantString())).Value.ToString();
|
||||
currentIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
var found = dictionaryVals.Any(x => x.Key.InvariantEquals(field.Key));
|
||||
if (found == false)
|
||||
{
|
||||
LogHelper.Warn<PreValueDisplayResolver>("Could not find persisted pre-value for field " + field.Key);
|
||||
continue;
|
||||
}
|
||||
field.Value = dictionaryVals.Single(x => x.Key.InvariantEquals(field.Key)).Value;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
MapPreValueValuesToPreValueFields(result, dictionaryVals, preVals.IsDictionaryBased);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using Umbraco.Core.Models.Editors;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to dynamically change the tag group based on the pre-values
|
||||
/// </summary>
|
||||
internal class TagPropertyEditorTagDefinition : TagPropertyDefinition
|
||||
{
|
||||
public TagPropertyEditorTagDefinition(ContentPropertyData propertySaving, SupportTagsAttribute tagsAttribute)
|
||||
: base(propertySaving, tagsAttribute)
|
||||
{
|
||||
}
|
||||
|
||||
public override string TagGroup
|
||||
{
|
||||
get
|
||||
{
|
||||
var preVals = PropertySaving.PreValues.FormatAsDictionary();
|
||||
return preVals.ContainsKey("group") ? preVals["group"].Value : "default";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,55 @@
|
||||
using Umbraco.Core;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
[SupportTags]
|
||||
[SupportTags(typeof(TagPropertyEditorTagDefinition))]
|
||||
[PropertyEditor(Constants.PropertyEditors.TagsAlias, "Tags", "tags")]
|
||||
public class TagsPropertyEditor : PropertyEditor
|
||||
{
|
||||
public TagsPropertyEditor()
|
||||
{
|
||||
_defaultPreVals = new Dictionary<string, object>
|
||||
{
|
||||
{"group", "default"}
|
||||
};
|
||||
}
|
||||
|
||||
private IDictionary<string, object> _defaultPreVals;
|
||||
|
||||
/// <summary>
|
||||
/// Override to supply the default group
|
||||
/// </summary>
|
||||
public override IDictionary<string, object> DefaultPreValues
|
||||
{
|
||||
get { return _defaultPreVals; }
|
||||
set { _defaultPreVals = value; }
|
||||
}
|
||||
|
||||
protected override PreValueEditor CreatePreValueEditor()
|
||||
{
|
||||
return new TagPreValueEditor();
|
||||
}
|
||||
|
||||
internal class TagPreValueEditor : PreValueEditor
|
||||
{
|
||||
public TagPreValueEditor()
|
||||
{
|
||||
Fields.Add(new PreValueField(new ManifestPropertyValidator { Type = "Required" })
|
||||
{
|
||||
Description = "Define a tag group",
|
||||
Key = "group",
|
||||
Name = "Tag group",
|
||||
View = "requiredfield"
|
||||
});
|
||||
}
|
||||
|
||||
public override IDictionary<string, object> ConvertDbToEditor(IDictionary<string, object> defaultPreVals, Core.Models.PreValueCollection persistedPreVals)
|
||||
{
|
||||
var result = base.ConvertDbToEditor(defaultPreVals, persistedPreVals);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -384,6 +384,7 @@
|
||||
<Compile Include="PropertyEditors\RadioButtonsPropertyEditor.cs" />
|
||||
<Compile Include="PropertyEditors\RichTextPreValueController.cs" />
|
||||
<Compile Include="PropertyEditors\RichTextPreValueEditor.cs" />
|
||||
<Compile Include="PropertyEditors\TagPropertyEditorTagDefinition.cs" />
|
||||
<Compile Include="PropertyEditors\UltraSimplePropertyEditor.cs" />
|
||||
<Compile Include="PropertyEditors\TagsPropertyEditor.cs" />
|
||||
<Compile Include="PropertyEditors\UploadFileTypeValidator.cs" />
|
||||
|
||||
Reference in New Issue
Block a user