Refactor editing

This commit is contained in:
Stephan
2018-02-15 14:49:32 +01:00
parent d30842e1bf
commit cfd2ba3b5a
96 changed files with 1083 additions and 1162 deletions
@@ -7,7 +7,7 @@ using LightInject;
// ReSharper disable once CheckNamespace
namespace Umbraco.Core.PropertyEditors
{
public class PropertyEditorResolver : LazyManyObjectsResolverBase<PropertyEditorCollectionBuilder, PropertyEditorCollection, PropertyEditor>
public class PropertyEditorResolver : LazyManyObjectsResolverBase<PropertyEditorCollectionBuilder, PropertyEditorCollection, ConfiguredDataEditor>
{
private PropertyEditorResolver(PropertyEditorCollectionBuilder builder)
: base(builder)
@@ -16,8 +16,8 @@ namespace Umbraco.Core.PropertyEditors
public static PropertyEditorResolver Current { get; }
= new PropertyEditorResolver(CoreCurrent.Container.GetInstance<PropertyEditorCollectionBuilder>());
public IEnumerable<PropertyEditor> PropertyEditors => CoreCurrent.PropertyEditors;
public IEnumerable<ConfiguredDataEditor> PropertyEditors => CoreCurrent.PropertyEditors;
public PropertyEditor GetByAlias(string alias) => CoreCurrent.PropertyEditors[alias];
public ConfiguredDataEditor GetByAlias(string alias) => CoreCurrent.PropertyEditors[alias];
}
}
@@ -12,35 +12,11 @@ namespace Umbraco.Core.Composing
internal static class TypeLoaderExtensions
{
/// <summary>
/// Gets all classes inheriting from PropertyEditor.
/// Gets all classes implementing <see cref="IDataEditor"/>.
/// </summary>
/// <remarks>
/// <para>Excludes the actual PropertyEditor base type.</para>
/// </remarks>
public static IEnumerable<Type> GetPropertyEditors(this TypeLoader mgr)
public static IEnumerable<Type> GetDataEditors(this TypeLoader mgr)
{
// look for IParameterEditor (fast, IDiscoverable) then filter
var propertyEditor = typeof (PropertyEditor);
return mgr.GetTypes<IParameterEditor>()
.Where(x => propertyEditor.IsAssignableFrom(x) && x != propertyEditor);
}
/// <summary>
/// Gets all classes implementing IParameterEditor.
/// </summary>
/// <remarks>
/// <para>Includes property editors.</para>
/// <para>Excludes the actual ParameterEditor and PropertyEditor base types.</para>
/// </remarks>
public static IEnumerable<Type> GetParameterEditors(this TypeLoader mgr)
{
var propertyEditor = typeof (PropertyEditor);
var parameterEditor = typeof (ParameterEditor);
return mgr.GetTypes<IParameterEditor>()
.Where(x => x != propertyEditor && x != parameterEditor);
return mgr.GetTypes<IDataEditor>();
}
/// <summary>
@@ -0,0 +1,155 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Serialization;
namespace Umbraco.Core.Manifest
{
/// <summary>
/// Provides a json read converter for <see cref="IDataEditor"/> in manifests.
/// </summary>
internal class DataEditorConverter : JsonReadConverter<IDataEditor>
{
private readonly ILogger _logger;
/// <summary>
/// Initializes a new instance of the <see cref="DataEditorConverter"/> class.
/// </summary>
public DataEditorConverter(ILogger logger)
{
_logger = logger;
}
/// <inheritdoc />
protected override IDataEditor Create(Type objectType, JObject jobject)
{
// in PackageManifest, property editors are IConfiguredDataEditor[] whereas
// parameter editors are IDataEditor[] - both will end up here because we handle
// IDataEditor and IConfiguredDataEditor implements it, but we can check the
// type to figure out what to create
if (objectType == typeof(IConfiguredDataEditor))
{
// property editor
var type = EditorType.PropertyValue;
if (jobject["isParameterEditor"] is JToken jToken && jToken.Value<bool>())
type &= EditorType.MacroParameter;
return new ConfiguredDataEditor(_logger, type);
}
else
{
// parameter editor
return new DataEditor(EditorType.MacroParameter);
}
}
/// <inheritdoc />
protected override void Deserialize(JObject jobject, IDataEditor target, JsonSerializer serializer)
{
// see Create above, target is either DataEditor (parameter) or ConfiguredDataEditor (property)
if (target is ConfiguredDataEditor configuredEditor)
{
// property editor
PrepareForPropertyEditor(jobject, configuredEditor);
}
else if (target is DataEditor editor)
{
// parameter editor
PrepareForParameterEditor(jobject, editor);
}
else throw new Exception("panic.");
base.Deserialize(jobject, target, serializer);
}
private static void PrepareForPropertyEditor(JObject jobject, ConfiguredDataEditor target)
{
if (jobject["editor"] != null)
{
// explicitely assign a value editor of type ValueEditor
// (else the deserializer will try to read it before setting it)
// (and besides it's an interface)
target.ValueEditor = new DataValueEditor();
// in the manifest, validators are a simple dictionary eg
// {
// required: true,
// regex: '\\d*'
// }
// and we need to turn this into a list of IPropertyValidator
// so, rewrite the json structure accordingly
if (jobject["editor"]["validation"] is JObject validation)
jobject["editor"]["validation"] = RewriteValidators(validation);
}
if (jobject["prevalues"] is JObject prevalues)
{
// explicitely assign a configuration editor of type ConfigurationEditor
// (else the deserializer will try to read it before setting it)
// (and besides it's an interface)
target.ConfigurationEditor = new ConfigurationEditor();
// see note about validators, above - same applies to field validators
if (jobject["prevalues"]?["fields"] is JArray jarray)
{
foreach (var field in jarray)
{
if (field["validation"] is JObject validation)
field["validation"] = RewriteValidators(validation);
}
}
// in the manifest, default configuration is at editor level
// move it down to configuration editor level so it can be deserialized properly
if (jobject["defaultConfig"] is JObject defaultConfig)
{
prevalues["defaultConfig"] = defaultConfig;
jobject.Remove("defaultConfig");
}
}
}
private static void PrepareForParameterEditor(JObject jobject, DataEditor target)
{
// in a manifest, a parameter editor looks like:
//
// {
// "alias": "...",
// "name": "...",
// "view": "...",
// "config": { "key1": "value1", "key2": "value2" ... }
// }
//
// the view is at top level, but should be down one level to be propertly
// deserialized as a ParameterValueEditor property -> need to move it
if (jobject.Property("view") != null)
{
// explicitely assign a value editor of type ParameterValueEditor
target.ValueEditor = new DataValueEditor();
// move the 'view' property
jobject["editor"] = new JObject { ["view"] = jobject["view"] };
jobject.Property("view").Remove();
}
}
private static JArray RewriteValidators(JObject validation)
{
var jarray = new JArray();
foreach (var v in validation)
{
var key = v.Key;
var val = v.Value?.Type == JTokenType.Boolean ? string.Empty : v.Value;
var jo = new JObject { { "type", key }, { "config", val } };
jarray.Add(jo);
}
return jarray;
}
}
}
+10 -5
View File
@@ -59,7 +59,7 @@ namespace Umbraco.Core.Manifest
{
var manifests = GetManifests();
return MergeManifests(manifests);
});
}, new TimeSpan(0, 4, 0));
/// <summary>
/// Gets all manifests.
@@ -95,8 +95,8 @@ namespace Umbraco.Core.Manifest
{
var scripts = new HashSet<string>();
var stylesheets = new HashSet<string>();
var propertyEditors = new List<PropertyEditor>();
var parameterEditors = new List<ParameterEditor>();
var propertyEditors = new List<IConfiguredDataEditor>();
var parameterEditors = new List<IDataEditor>();
var gridEditors = new List<GridEditor>();
foreach (var manifest in manifests)
@@ -140,8 +140,7 @@ namespace Umbraco.Core.Manifest
throw new ArgumentNullOrEmptyException(nameof(text));
var manifest = JsonConvert.DeserializeObject<PackageManifest>(text,
new PropertyEditorConverter(_logger),
new ParameterEditorConverter(),
new DataEditorConverter(_logger),
new ManifestValidatorConverter(_validators));
// scripts and stylesheets are raw string, must process here
@@ -150,6 +149,12 @@ namespace Umbraco.Core.Manifest
for (var i = 0; i < manifest.Stylesheets.Length; i++)
manifest.Stylesheets[i] = IOHelper.ResolveVirtualUrl(manifest.Stylesheets[i]);
// add property editors that are also parameter editors, to the parameter editors list
// (the manifest format is kinda legacy)
var ppEditors = manifest.PropertyEditors.Where(x => (x.Type & EditorType.MacroParameter) > 0).ToList();
if (ppEditors.Count > 0)
manifest.ParameterEditors = manifest.ParameterEditors.Union(ppEditors).ToArray();
return manifest;
}
+2 -2
View File
@@ -16,10 +16,10 @@ namespace Umbraco.Core.Manifest
public string[] Stylesheets { get; set; }= Array.Empty<string>();
[JsonProperty("propertyEditors")]
public PropertyEditor[] PropertyEditors { get; set; } = Array.Empty<PropertyEditor>();
public IConfiguredDataEditor[] PropertyEditors { get; set; } = Array.Empty<IConfiguredDataEditor>();
[JsonProperty("parameterEditors")]
public ParameterEditor[] ParameterEditors { get; set; } = Array.Empty<ParameterEditor>();
public IDataEditor[] ParameterEditors { get; set; } = Array.Empty<IDataEditor>();
[JsonProperty("gridEditors")]
public GridEditor[] GridEditors { get; set; } = Array.Empty<GridEditor>();
@@ -1,48 +0,0 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Serialization;
namespace Umbraco.Core.Manifest
{
/// <summary>
/// Implements a json read converter for <see cref="ParameterEditor"/>.
/// </summary>
internal class ParameterEditorConverter : JsonReadConverter<ParameterEditor>
{
/// <inheritdoc />
protected override ParameterEditor Create(Type objectType, JObject jObject)
{
return new ParameterEditor();
}
/// <inheritdoc />
protected override void Deserialize(JObject jobject, ParameterEditor target, JsonSerializer serializer)
{
// in a manifest, a parameter editor looks like:
//
// {
// "alias": "...",
// "name": "...",
// "view": "...",
// "config": { "key1": "value1", "key2": "value2" ... }
// }
//
// the view is at top level, but should be down one level to be propertly
// deserialized as a ParameterValueEditor property -> need to move it
if (jobject.Property("view") != null)
{
// explicitely assign a value editor of type ParameterValueEditor
target.ValueEditor = new ParameterValueEditor();
// move the 'view' property
jobject["editor"] = new JObject { ["view"] = jobject["view"] };
jobject.Property("view").Remove();
}
base.Deserialize(jobject, target, serializer);
}
}
}
@@ -1,96 +0,0 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Serialization;
namespace Umbraco.Core.Manifest
{
/// <summary>
/// Implements a json read converter for <see cref="PropertyEditor"/>.
/// </summary>
internal class PropertyEditorConverter : JsonReadConverter<PropertyEditor>
{
private readonly ILogger _logger;
/// <summary>
/// Initializes a new instance of the <see cref="PropertyEditorConverter"/> class.
/// </summary>
public PropertyEditorConverter(ILogger logger)
{
_logger = logger;
}
/// <inheritdoc />
protected override PropertyEditor Create(Type objectType, JObject jObject)
{
return new PropertyEditor(_logger);
}
/// <inheritdoc />
protected override void Deserialize(JObject jobject, PropertyEditor target, JsonSerializer serializer)
{
if (jobject["editor"] != null)
{
// explicitely assign a value editor of type ValueEditor
// (else the deserializer will try to read it before setting it)
// (and besides it's an interface)
target.ValueEditor = new ValueEditor();
// in the manifest, validators are a simple dictionary eg
// {
// required: true,
// regex: '\\d*'
// }
// and we need to turn this into a list of IPropertyValidator
// so, rewrite the json structure accordingly
if (jobject["editor"]["validation"] is JObject validation)
jobject["editor"]["validation"] = RewriteValidators(validation);
}
if (jobject["prevalues"] is JObject prevalues)
{
// explicitely assign a configuration editor of type ConfigurationEditor
// (else the deserializer will try to read it before setting it)
// (and besides it's an interface)
target.ConfigurationEditor = new ConfigurationEditor();
// see note about validators, above - same applies to field validators
if (jobject["prevalues"]?["fields"] is JArray jarray)
{
foreach (var field in jarray)
{
if (field["validation"] is JObject validation)
field["validation"] = RewriteValidators(validation);
}
}
// in the manifest, default configuration is at editor level
// move it down to configuration editor level so it can be deserialized properly
if (jobject["defaultConfig"] is JObject defaultConfig)
{
prevalues["defaultConfig"] = defaultConfig;
jobject.Remove("defaultConfig");
}
}
base.Deserialize(jobject, target, serializer);
}
private static JArray RewriteValidators(JObject validation)
{
var jarray = new JArray();
foreach (var v in validation)
{
var key = v.Key;
var val = v.Value?.Type == JTokenType.Boolean ? string.Empty : v.Value;
var jo = new JObject { { "type", key }, { "config", val } };
jarray.Add(jo);
}
return jarray;
}
}
}
+4 -4
View File
@@ -17,7 +17,7 @@ namespace Umbraco.Core.Models
{
private static PropertySelectors _selectors;
private PropertyEditor _editor;
private IConfiguredDataEditor _editor;
private ValueStorageType _databaseType;
private object _configuration;
private bool _hasConfiguration;
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Initializes a new instance of the <see cref="DataType"/> class.
/// </summary>
public DataType(PropertyEditor editor, int parentId = -1)
public DataType(IConfiguredDataEditor editor, int parentId = -1)
{
_editor = editor ?? throw new ArgumentNullException(nameof(editor));
ParentId = parentId;
@@ -36,14 +36,14 @@ namespace Umbraco.Core.Models
private class PropertySelectors
{
public readonly PropertyInfo Editor = ExpressionHelper.GetPropertyInfo<DataType, PropertyEditor>(x => x.Editor);
public readonly PropertyInfo Editor = ExpressionHelper.GetPropertyInfo<DataType, IDataEditor>(x => x.Editor);
public readonly PropertyInfo DatabaseType = ExpressionHelper.GetPropertyInfo<DataType, ValueStorageType>(x => x.DatabaseType);
public readonly PropertyInfo Configuration = ExpressionHelper.GetPropertyInfo<DataType, object>(x => x.Configuration);
}
/// <inheritdoc />
[IgnoreDataMember]
public PropertyEditor Editor
public IConfiguredDataEditor Editor
{
get => _editor;
set
+1 -1
View File
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Gets or sets the property editor.
/// </summary>
PropertyEditor Editor { get; set; }
IConfiguredDataEditor Editor { get; set; }
/// <summary>
/// Gets the property editor alias.
@@ -8,7 +8,7 @@ namespace Umbraco.Core.PropertyEditors
/// <summary>
/// Represents a data type configuration editor.
/// </summary>
public class ConfigurationEditor
public class ConfigurationEditor : IConfigurationEditor
{
/// <summary>
/// Initializes a new instance of the <see cref="ConfigurationEditor"/> class.
@@ -33,7 +33,7 @@ namespace Umbraco.Core.PropertyEditors
public List<ConfigurationField> Fields { get; }
/// <summary>
/// Gets a field by property name.
/// Gets a field by its property name.
/// </summary>
/// <remarks>Can be used in constructors to add infos to a field that has been defined
/// by a property marked with the <see cref="ConfigurationFieldAttribute"/>.</remarks>
@@ -50,41 +50,20 @@ namespace Umbraco.Core.PropertyEditors
throw new InvalidCastException($"Cannot cast configuration of type {obj.GetType().Name} to {typeof(TConfiguration).Name}.");
}
/// <summary>
/// Gets the default configuration.
/// </summary>
/// <remarks>
/// <para>The default configuration is used to initialize new datatypes.</para>
/// </remarks>
/// <inheritdoc />
[JsonProperty("defaultConfig")]
public virtual IDictionary<string, object> DefaultConfiguration => new Dictionary<string, object>();
/// <summary>
/// Determines whether a configuration object is of the type expected by the configuration editor.
/// </summary>
public virtual bool IsConfiguration(object obj)
=> obj is IDictionary<string, object>;
/// <inheritdoc />
public virtual bool IsConfiguration(object obj) => obj is IDictionary<string, object>;
// notes
// ToConfigurationEditor returns a dictionary, and FromConfigurationEditor accepts a dictionary.
// this is due to the way our front-end editors work, see DataTypeController.PostSave
// and DataTypeConfigurationFieldDisplayResolver - we are not going to change it now.
/// <summary>
/// Converts the serialized database value into the actual configuration object.
/// </summary>
/// <remarks>Converting the configuration object to the serialized database value is
/// achieved by simply serializing the configuration.</remarks>
/// <inheritdoc />
public virtual object FromDatabase(string configurationJson)
=> string.IsNullOrWhiteSpace(configurationJson)
? new Dictionary<string, object>()
: JsonConvert.DeserializeObject<Dictionary<string, object>>(configurationJson);
/// <summary>
/// Converts the values posted by the configuration editor into the actual configuration object.
/// </summary>
/// <param name="editorValues">The values posted by the configuration editor.</param>
/// <param name="configuration">The current configuration object.</param>
/// <inheritdoc />
public virtual object FromConfigurationEditor(Dictionary<string, object> editorValues, object configuration)
{
// by default, return the posted dictionary
@@ -97,10 +76,7 @@ namespace Umbraco.Core.PropertyEditors
return editorValues;
}
/// <summary>
/// Converts the configuration object to values for the configuration editor.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <inheritdoc />
public virtual Dictionary<string, object> ToConfigurationEditor(object configuration)
{
// editors that do not override ToEditor/FromEditor have their configuration
@@ -120,10 +96,7 @@ namespace Umbraco.Core.PropertyEditors
return d;
}
/// <summary>
/// Converts the configuration object to values for the value editror.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <inheritdoc />
public virtual Dictionary<string, object> ToValueEditor(object configuration)
=> ToConfigurationEditor(configuration);
}
@@ -1,208 +1,192 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Newtonsoft.Json;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Provides a base class for property editors.
/// </summary>
/// <remarks>
/// <para>Editors can be deserialized from manifests, which is why the Json serialization
/// attributes are required, and the properties require an internal setter.</para>
/// </remarks>
[DebuggerDisplay("{" + nameof(DebuggerDisplay) + "(),nq}")]
public class PropertyEditor : IParameterEditor
{
private IPropertyValueEditor _valueEditorAssigned;
private ConfigurationEditor _configurationEditorAssigned;
/// <summary>
/// Initializes a new instance of the <see cref="PropertyEditor"/> class.
/// </summary>
public PropertyEditor(ILogger logger)
{
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
// defaults
Icon = Constants.Icons.PropertyEditor;
Group = "common";
// assign properties based on the attribute, if it is found
Attribute = GetType().GetCustomAttribute<ValueEditorAttribute>(false);
if (Attribute == null) return;
Alias = Attribute.Alias;
Name = Attribute.Name;
IsParameterEditor = Attribute.IsMacroParameterEditor;
Icon = Attribute.Icon;
Group = Attribute.Group;
IsDeprecated = Attribute.IsDeprecated;
}
/// <summary>
/// Gets the editor attribute.
/// </summary>
protected ValueEditorAttribute Attribute { get; }
/// <summary>
/// Gets a logger.
/// </summary>
protected ILogger Logger { get; }
/// <summary>
/// Gets or sets a value indicating whether this editor can be used as a parameter editor.
/// </summary>
[JsonProperty("isParameterEditor")]
public bool IsParameterEditor { get; internal set; } // fixme understand + explain
/// <summary>
/// Gets or sets the unique alias of the property editor.
/// </summary>
[JsonProperty("alias", Required = Required.Always)]
public string Alias { get; internal set; }
/// <summary>
/// Gets or sets the name of the property editor.
/// </summary>
[JsonProperty("name", Required = Required.Always)]
public string Name { get; internal set; }
/// <summary>
/// Gets or sets the icon of the property editor.
/// </summary>
[JsonProperty("icon")]
public string Icon { get; internal set; }
/// <summary>
/// Gets or sets the group of the property editor.
/// </summary>
/// <remarks>The group can be used to group editors by categories.</remarks>
[JsonProperty("group")]
public string Group { get; internal set; }
/// <summary>
/// Gets or sets a value indicating whether the property editor is deprecated.
/// </summary>
/// <remarks>A deprecated editor does not show up in the list of available editors for a datatype,
/// unless it is the current editor for the datatype.</remarks>
[JsonIgnore]
public bool IsDeprecated { get; internal set; }
/// <summary>
/// Gets or sets the value editor.
/// </summary>
/// <remarks>
/// <para>If an instance of a value editor is assigned to the property,
/// then this instance is returned when getting the property value. Otherwise, a
/// new instance is created by CreateValueEditor.</para>
/// <para>The instance created by CreateValueEditor is not cached, i.e.
/// a new instance is created each time the property value is retrieved. The
/// property editor is a singleton, and the value editor cannot be a singleton
/// since it depends on the datatype configuration.</para>
/// <para>Technically, it could be cached by datatype but let's keep things
/// simple enough for now.</para>
/// <para>The property is *not* marked with json ObjectCreationHandling = ObjectCreationHandling.Replace,
/// so by default the deserializer will first try to read it before assigning it, which is why
/// all deserialization *should* set the property before anything (see manifest deserializer).</para>
/// </remarks>
[JsonProperty("editor", Required = Required.Always)]
public IPropertyValueEditor ValueEditor
{
// create a new value editor each time - the property editor can be a
// singleton, but the value editor will get a configuration which depends
// on the datatype, so it cannot be a singleton really
get => CreateValueEditor();
set => _valueEditorAssigned = value;
}
/// <inheritdoc />
[JsonIgnore]
IValueEditor IParameterEditor.ValueEditor => ValueEditor;
/// <summary>
/// Gets or sets the configuration editor.
/// </summary>
/// <remarks>
/// <para>If an instance of a configuration editor is assigned to the property,
/// then this instance is returned when getting the property value. Otherwise, a
/// new instance is created by CreateConfigurationEditor.</para>
/// <para>The instance created by CreateConfigurationEditor is not cached, i.e.
/// a new instance is created each time the property value is retrieved. The
/// property editor is a singleton, and although the configuration editor could
/// technically be a singleton too, we'd rather not keep configuration editor
/// cached.</para>
/// <para>The property is *not* marked with json ObjectCreationHandling = ObjectCreationHandling.Replace,
/// so by default the deserializer will first try to read it before assigning it, which is why
/// all deserialization *should* set the property before anything (see manifest deserializer).</para>
/// </remarks>
[JsonProperty("prevalues")] // changing the name would break manifests
public ConfigurationEditor ConfigurationEditor
{
get => CreateConfigurationEditor();
set => _configurationEditorAssigned = value;
}
// a property editor has a configuration editor which is in charge of all configuration
// a parameter editor does not have a configuration editor and directly handles its configuration
// when a property editor can also be a parameter editor it needs to expose the configuration
// fixme but that's only for some property editors
[JsonIgnore]
IDictionary<string, object> IParameterEditor.Configuration => ConfigurationEditor.DefaultConfiguration;
/// <summary>
/// Creates a value editor instance.
/// </summary>
protected virtual IPropertyValueEditor CreateValueEditor()
{
// handle assigned editor
// or create a new editor
return _valueEditorAssigned ?? new ValueEditor(Attribute);
}
/// <summary>
/// Creates a configuration editor instance.
/// </summary>
protected virtual ConfigurationEditor CreateConfigurationEditor()
{
// handle assigned editor
if (_configurationEditorAssigned != null)
return _configurationEditorAssigned;
// else return an empty one
return new ConfigurationEditor();
}
protected bool Equals(PropertyEditor other)
{
return string.Equals(Alias, other.Alias);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((PropertyEditor) obj);
}
public override int GetHashCode()
{
// an internal setter is required for de-serialization from manifests
// but we are never going to change the alias once the editor exists
// ReSharper disable once NonReadonlyMemberInGetHashCode
return Alias.GetHashCode();
}
/// <summary>
/// Provides a summary of the PropertyEditor for use with the <see cref="DebuggerDisplayAttribute"/>.
/// </summary>
protected virtual string DebuggerDisplay()
{
return $"Name: {Name}, Alias: {Alias}, IsParameterEditor: {IsParameterEditor}";
}
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Newtonsoft.Json;
using Umbraco.Core.Composing;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Provides a base class for property editors. fixme rewrite
/// </summary>
/// <remarks>
/// <para>Editors can be deserialized from manifests, which is why the Json serialization
/// attributes are required, and the properties require an internal setter.</para>
/// </remarks>
[DebuggerDisplay("{" + nameof(DebuggerDisplay) + "(),nq}")]
[HideFromTypeFinder]
public class ConfiguredDataEditor : IConfiguredDataEditor
{
private IDataValueEditor _valueEditorAssigned;
private IConfigurationEditor _configurationEditorAssigned;
/// <summary>
/// Initializes a new instance of the <see cref="ConfiguredDataEditor"/> class.
/// </summary>
public ConfiguredDataEditor(ILogger logger, EditorType type = EditorType.PropertyValue)
{
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
// defaults
Type = type;
Icon = Constants.Icons.PropertyEditor;
Group = "common";
// assign properties based on the attribute, if it is found
Attribute = GetType().GetCustomAttribute<DataEditorAttribute>(false);
if (Attribute == null) return;
Alias = Attribute.Alias;
Type = Attribute.Type;
Name = Attribute.Name;
Icon = Attribute.Icon;
Group = Attribute.Group;
IsDeprecated = Attribute.IsDeprecated;
}
/// <summary>
/// Gets the editor attribute.
/// </summary>
protected DataEditorAttribute Attribute { get; }
/// <summary>
/// Gets a logger.
/// </summary>
protected ILogger Logger { get; }
/// <inheritdoc />
[JsonProperty("alias", Required = Required.Always)]
public string Alias { get; internal set; }
/// <inheritdoc />
[JsonIgnore]
public EditorType Type { get; }
/// <inheritdoc />
[JsonProperty("name", Required = Required.Always)]
public string Name { get; internal set; }
/// <inheritdoc />
[JsonProperty("icon")]
public string Icon { get; internal set; }
/// <inheritdoc />
[JsonProperty("group")]
public string Group { get; internal set; }
/// <summary>
/// Gets or sets a value indicating whether the property editor is deprecated.
/// </summary>
/// <remarks>A deprecated editor does not show up in the list of available editors for a datatype,
/// unless it is the current editor for the datatype.</remarks>
[JsonIgnore]
public bool IsDeprecated { get; internal set; } // fixme on interface?
[JsonProperty("preValues")]
public IDictionary<string, object> DefaultConfiguration => ConfigurationEditor.DefaultConfiguration;
/// <summary>
/// Gets or sets the value editor.
/// </summary>
/// <remarks>
/// <para>If an instance of a value editor is assigned to the property,
/// then this instance is returned when getting the property value. Otherwise, a
/// new instance is created by CreateValueEditor.</para>
/// <para>The instance created by CreateValueEditor is not cached, i.e.
/// a new instance is created each time the property value is retrieved. The
/// property editor is a singleton, and the value editor cannot be a singleton
/// since it depends on the datatype configuration.</para>
/// <para>Technically, it could be cached by datatype but let's keep things
/// simple enough for now.</para>
/// <para>The property is *not* marked with json ObjectCreationHandling = ObjectCreationHandling.Replace,
/// so by default the deserializer will first try to read it before assigning it, which is why
/// all deserialization *should* set the property before anything (see manifest deserializer).</para>
/// </remarks>
[JsonProperty("editor", Required = Required.Always)]
public IDataValueEditor ValueEditor
{
// create a new value editor each time - the property editor can be a
// singleton, but the value editor will get a configuration which depends
// on the datatype, so it cannot be a singleton really
get => CreateValueEditor();
set => _valueEditorAssigned = value;
}
/// <summary>
/// Gets or sets the configuration editor.
/// </summary>
/// <remarks>
/// <para>If an instance of a configuration editor is assigned to the property,
/// then this instance is returned when getting the property value. Otherwise, a
/// new instance is created by CreateConfigurationEditor.</para>
/// <para>The instance created by CreateConfigurationEditor is not cached, i.e.
/// a new instance is created each time the property value is retrieved. The
/// property editor is a singleton, and although the configuration editor could
/// technically be a singleton too, we'd rather not keep configuration editor
/// cached.</para>
/// <para>The property is *not* marked with json ObjectCreationHandling = ObjectCreationHandling.Replace,
/// so by default the deserializer will first try to read it before assigning it, which is why
/// all deserialization *should* set the property before anything (see manifest deserializer).</para>
/// </remarks>
[JsonProperty("prevalues")] // changing the name would break manifests
public IConfigurationEditor ConfigurationEditor
{
get => CreateConfigurationEditor();
set => _configurationEditorAssigned = value;
}
/// <summary>
/// Creates a value editor instance.
/// </summary>
protected virtual IDataValueEditor CreateValueEditor()
{
// handle assigned editor
// or create a new editor
return _valueEditorAssigned ?? new DataValueEditor(Attribute);
}
/// <summary>
/// Creates a configuration editor instance.
/// </summary>
protected virtual IConfigurationEditor CreateConfigurationEditor()
{
// handle assigned editor
if (_configurationEditorAssigned != null)
return _configurationEditorAssigned;
// else return an empty one
return new ConfigurationEditor();
}
protected bool Equals(ConfiguredDataEditor other)
{
return string.Equals(Alias, other.Alias);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((ConfiguredDataEditor) obj);
}
public override int GetHashCode()
{
// an internal setter is required for de-serialization from manifests
// but we are never going to change the alias once the editor exists
// ReSharper disable once NonReadonlyMemberInGetHashCode
return Alias.GetHashCode();
}
/// <summary>
/// Provides a summary of the PropertyEditor for use with the <see cref="DebuggerDisplayAttribute"/>.
/// </summary>
protected virtual string DebuggerDisplay()
{
return $"Name: {Name}, Alias: {Alias}";
}
}
}
@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Umbraco.Core.Composing;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Represents a parameter editor. fixme rewrite
/// </summary>
/// <remarks>
/// <para>Is not abstract because can be instanciated from manifests.</para>
/// </remarks>
[HideFromTypeFinder]
public class DataEditor : IDataEditor
{
private IDataValueEditor _valueEditor;
private IDataValueEditor _valueEditorAssigned;
/// <summary>
/// Initializes a new instance of the <see cref="DataEditor"/> class.
/// </summary>
public DataEditor(EditorType type = EditorType.PropertyValue)
{
// defaults
Type = type;
Icon = Constants.Icons.PropertyEditor;
Group = "common";
DefaultConfiguration = new Dictionary<string, object>();
// assign properties based on the attribute, if it is found
Attribute = GetType().GetCustomAttribute<DataEditorAttribute>(false);
if (Attribute == null) return;
Alias = Attribute.Alias;
Type = Attribute.Type;
Name = Attribute.Name;
}
/// <summary>
/// Gets the editor attribute.
/// </summary>
protected DataEditorAttribute Attribute { get; }
/// <inheritdoc />
[JsonProperty("alias", Required = Required.Always)]
public string Alias { get; internal set; }
/// <inheritdoc />
[JsonIgnore]
public EditorType Type { get; }
/// <inheritdoc />
[JsonProperty("name", Required = Required.Always)]
public string Name { get; internal set; }
/// <inheritdoc />
[JsonProperty("icon")]
public string Icon { get; }
/// <inheritdoc />
[JsonProperty("group")]
public string Group { get; }
/// <inheritdoc />
[JsonProperty("editor")]
public IDataValueEditor ValueEditor
{
get => _valueEditor ?? (_valueEditor = CreateValueEditor());
set
{
_valueEditorAssigned = value;
_valueEditor = null;
}
}
/// <inheritdoc />
[JsonProperty("config")]
public IDictionary<string, object> DefaultConfiguration { get; set; }
/// <summary>
/// Creates a value editor instance.
/// </summary>
/// <returns></returns>
protected virtual IDataValueEditor CreateValueEditor()
{
// handle assigned editor
if (_valueEditorAssigned != null)
return _valueEditorAssigned;
// create a new editor
var editor = new DataValueEditor();
var view = Attribute?.View;
if (string.IsNullOrWhiteSpace(view))
throw new InvalidOperationException("The editor does not specify a view.");
editor.View = view;
return editor;
}
}
}
@@ -6,20 +6,63 @@ namespace Umbraco.Core.PropertyEditors
/// <summary>
/// Marks a class that represents a data editor.
/// </summary>
public abstract class DataEditorAttribute : Attribute
[AttributeUsage(AttributeTargets.Class)]
public sealed class DataEditorAttribute : Attribute
{
private string _valueType = ValueTypes.String;
/// <summary>
/// Initializes a new instance of the <see cref="ParameterEditorAttribute"/> class.
/// Initializes a new instance of the <see cref="DataEditorAttribute"/> class for a property editor.
/// </summary>
/// <param name="alias">The unique identifier of the editor.</param>
/// <param name="name">The friendly name of the editor.</param>
public DataEditorAttribute(string alias, string name)
: this(alias, EditorType.PropertyValue, name, NullView)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="DataEditorAttribute"/> class for a property editor.
/// </summary>
/// <param name="alias">The unique identifier of the editor.</param>
/// <param name="name">The friendly name of the editor.</param>
/// <param name="view">The view to use to render the editor.</param>
public DataEditorAttribute(string alias, string name, string view)
: this(alias, EditorType.PropertyValue, name, view)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="DataEditorAttribute"/> class.
/// </summary>
/// <param name="alias">The unique identifier of the editor.</param>
/// <param name="type">The type of the editor.</param>
/// <param name="name">The friendly name of the editor.</param>
public DataEditorAttribute(string alias, EditorType type, string name)
: this(alias, type, name, NullView)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="DataEditorAttribute"/> class.
/// </summary>
/// <param name="alias">The unique identifier of the editor.</param>
/// <param name="type">The type of the editor.</param>
/// <param name="name">The friendly name of the editor.</param>
/// <param name="view">The view to use to render the editor.</param>
/// <remarks>
/// <para>Set <paramref name="view"/> to <see cref="NullView"/> to explicitely set the view to null.</para>
/// <para>Otherwise, <paramref name="view"/> cannot be null nor empty.</para>
/// </remarks>
protected DataEditorAttribute(string alias, string name, string view)
public DataEditorAttribute(string alias, EditorType type, string name, string view)
{
switch (type) // Enum.IsDefined is slow
{
case EditorType.PropertyValue:
case EditorType.MacroParameter:
Type = type;
break;
default:
throw new ArgumentOutOfRangeException(nameof(type), $"Not a valid {typeof(EditorType)} value.");
}
if (string.IsNullOrWhiteSpace(alias)) throw new ArgumentNullOrEmptyException(nameof(alias));
Alias = alias;
@@ -33,21 +76,63 @@ namespace Umbraco.Core.PropertyEditors
/// <summary>
/// Gets a special value indicating that the view should be null.
/// </summary>
protected static string NullView = "EXPLICITELY-SET-VIEW-TO-NULL-2B5B0B73D3DD47B28DDB84E02C349DFB"; // just a random string
public const string NullView = "EXPLICITELY-SET-VIEW-TO-NULL-2B5B0B73D3DD47B28DDB84E02C349DFB"; // just a random string
/// <summary>
/// Gets the unique alias of the editor.
/// </summary>
public string Alias { get; }
/// <summary>
/// Gets the type of the editor.
/// </summary>
public EditorType Type { get; }
/// <summary>
/// Gets the friendly name of the editor.
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the view to use to render the editor.
/// Gets the view to use to render the editor. fixme - but that's for the VALUE really?
/// </summary>
public string View { get; }
/// <summary>
/// Gets or sets the type of the edited value.
/// </summary>
/// <remarks>Must be a valid <see cref="ValueTypes"/> value.</remarks>
public string ValueType {
get => _valueType;
set
{
if (string.IsNullOrWhiteSpace(value)) throw new ArgumentNullOrEmptyException(nameof(value));
if (!ValueTypes.IsValue(value)) throw new ArgumentOutOfRangeException(nameof(value), $"Not a valid {typeof(ValueTypes)} value.");
_valueType = value;
}
}
/// <summary>
/// Gets or sets a value indicating whether the editor should be displayed without its label.
/// </summary>
public bool HideLabel { get; set; }
/// <summary>
/// Gets or sets an optional icon.
/// </summary>
/// <remarks>The icon can be used for example when presenting datatypes based upon the editor.</remarks>
public string Icon { get; set; } = Constants.Icons.PropertyEditor;
/// <summary>
/// Gets or sets an optional group.
/// </summary>
/// <remarks>The group can be used for example to group the editors by category.</remarks>
public string Group { get; set; } = "common";
/// <summary>
/// Gets or sets a value indicating whether the value editor is deprecated.
/// </summary>
/// <remarks>A deprecated editor is still supported but not proposed in the UI.</remarks>
public bool IsDeprecated { get; set; }
}
}
@@ -14,25 +14,25 @@ using Umbraco.Core.Services;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Represents a value editor for content properties.
/// Represents a value editor.
/// </summary>
public class ValueEditor : IPropertyValueEditor
public class DataValueEditor : IDataValueEditor
{
private string _view;
/// <summary>
/// Initializes a new instance of the <see cref="ValueEditor"/> class.
/// Initializes a new instance of the <see cref="DataValueEditor"/> class.
/// </summary>
public ValueEditor() // for tests, and manifest
public DataValueEditor() // for tests, and manifest
{
ValueType = ValueTypes.String;
Validators = new List<IValueValidator>();
}
/// <summary>
/// Initializes a new instance of the <see cref="ValueEditor"/> class.
/// Initializes a new instance of the <see cref="DataValueEditor"/> class.
/// </summary>
public ValueEditor(string view, params IValueValidator[] validators) // not used
public DataValueEditor(string view, params IValueValidator[] validators) // not used
: this()
{
View = view;
@@ -40,9 +40,9 @@ namespace Umbraco.Core.PropertyEditors
}
/// <summary>
/// Initializes a new instance of the <see cref="ValueEditor"/> class.
/// Initializes a new instance of the <see cref="DataValueEditor"/> class.
/// </summary>
public ValueEditor(ValueEditorAttribute attribute)
public DataValueEditor(DataEditorAttribute attribute)
: this()
{
if (attribute == null) return;
@@ -240,7 +240,7 @@ namespace Umbraco.Core.PropertyEditors
var result = TryConvertValueToCrlType(editorValue.Value);
if (result.Success == false)
{
Current.Logger.Warn<ValueEditor>("The value " + editorValue.Value + " cannot be converted to the type " + ValueTypes.ToStorageType(ValueType));
Current.Logger.Warn<DataValueEditor>("The value " + editorValue.Value + " cannot be converted to the type " + ValueTypes.ToStorageType(ValueType));
return null;
}
return result.Result;
@@ -0,0 +1,56 @@
using System.Collections.Generic;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Represents an editor for editing the configuration of editors.
/// </summary>
public interface IConfigurationEditor
{
/// <summary>
/// Gets the fields.
/// </summary>
List<ConfigurationField> Fields { get; }
/// <summary>
/// Gets the default configuration.
/// </summary>
IDictionary<string, object> DefaultConfiguration { get; }
/// <summary>
/// Determines whether a configuration object is of the type expected by the configuration editor.
/// </summary>
bool IsConfiguration(object obj);
// notes
// ToConfigurationEditor returns a dictionary, and FromConfigurationEditor accepts a dictionary.
// this is due to the way our front-end editors work, see DataTypeController.PostSave
// and DataTypeConfigurationFieldDisplayResolver - we are not going to change it now.
/// <summary>
/// Converts the serialized database value into the actual configuration object.
/// </summary>
/// <remarks>Converting the configuration object to the serialized database value is
/// achieved by simply serializing the configuration.</remarks>
object FromDatabase(string configurationJson);
/// <summary>
/// Converts the values posted by the configuration editor into the actual configuration object.
/// </summary>
/// <param name="editorValues">The values posted by the configuration editor.</param>
/// <param name="configuration">The current configuration object.</param>
object FromConfigurationEditor(Dictionary<string, object> editorValues, object configuration);
/// <summary>
/// Converts the configuration object to values for the configuration editor.
/// </summary>
/// <param name="configuration">The configuration.</param>
Dictionary<string, object> ToConfigurationEditor(object configuration);
/// <summary>
/// Converts the configuration object to values for the value editror.
/// </summary>
/// <param name="configuration">The configuration.</param>
Dictionary<string, object> ToValueEditor(object configuration);
}
}
@@ -0,0 +1,13 @@
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Represents a data editor which can be configured.
/// </summary>
public interface IConfiguredDataEditor : IDataEditor
{
/// <summary>
/// Gets the editor to edit the value editor configuration.
/// </summary>
IConfigurationEditor ConfigurationEditor { get; } // fixme should be a method - but, deserialization?
}
}
@@ -0,0 +1,50 @@
using System.Collections.Generic;
using Umbraco.Core.Composing;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Represents a data editor.
/// </summary>
/// <remarks>This is the base interface for parameter and property editors.</remarks>
public interface IDataEditor : IDiscoverable
{
/// <summary>
/// Gets the alias of the editor.
/// </summary>
string Alias { get; }
/// <summary>
/// Gets the type of the editor.
/// </summary>
/// <remarks>An editor can be a property value editor, or a parameter editor.</remarks>
EditorType Type { get; }
/// <summary>
/// Gets the name of the editor.
/// </summary>
string Name { get; }
/// <summary>
/// Gets the icon of the editor.
/// </summary>
/// <remarks>Can be used to display editors when presenting them.</remarks>
string Icon { get; }
/// <summary>
/// Gets the group of the editor.
/// </summary>
/// <remarks>Can be used to organize editors when presenting them.</remarks>
string Group { get; }
/// <summary>
/// Gets the value editor.
/// </summary>
IDataValueEditor ValueEditor { get; } // fixme should be a method - but, deserialization?
/// <summary>
/// Gets the configuration for the value editor.
/// </summary>
IDictionary<string, object> DefaultConfiguration { get; }
}
}
@@ -1,45 +1,53 @@
using System.Collections.Generic;
using System.Xml.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
using Umbraco.Core.Services;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Represents an editor for editing values.
/// </summary>
public interface IValueEditor
{
/// <summary>
/// Gets the editor view.
/// </summary>
string View { get; }
/// <summary>
/// Gets the type of the value.
/// </summary>
/// <remarks>The value has to be a valid <see cref="ValueTypes"/> value.</remarks>
string ValueType { get; set; }
}
// fixme
public interface IPropertyValueEditor : IValueEditor
{
// fixme services should be injected!
object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue);
object ConvertDbToEditor(Property property, PropertyType propertyType, IDataTypeService dataTypeService);
IEnumerable<XElement> ConvertDbToXml(Property property, IDataTypeService dataTypeService, ILocalizationService localizationService, bool published);
XNode ConvertDbToXml(PropertyType propertyType, object value, IDataTypeService dataTypeService);
string ConvertDbToString(PropertyType propertyType, object value, IDataTypeService dataTypeService);
List<IValueValidator> Validators { get; }
bool IsReadOnly { get; }
bool HideLabel { get; }
// fixme what are these?
ManifestValidator RequiredValidator { get; }
ManifestValidator RegexValidator { get; }
}
}
using System.Collections.Generic;
using System.Xml.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
using Umbraco.Core.Services;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Represents an editor for editing data values.
/// </summary>
/// <remarks>This is the base interface for parameter and property value editors.</remarks>
public interface IDataValueEditor
{
/// <summary>
/// Gets the editor view.
/// </summary>
string View { get; }
/// <summary>
/// Gets the type of the value.
/// </summary>
/// <remarks>The value has to be a valid <see cref="ValueTypes"/> value.</remarks>
string ValueType { get; set; }
/// <summary>
/// Gets a value indicating whether the edited value is read-only.
/// </summary>
bool IsReadOnly { get; }
/// <summary>
/// Gets a value indicating whether to display the associated label.
/// </summary>
bool HideLabel { get; }
/// <summary>
/// Gets the validators to use to validate the edited value.
/// </summary>
List<IValueValidator> Validators { get; }
// fixme what are these?
ManifestValidator RequiredValidator { get; }
ManifestValidator RegexValidator { get; }
// fixme services should be injected!
// fixme document
object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue);
object ConvertDbToEditor(Property property, PropertyType propertyType, IDataTypeService dataTypeService);
IEnumerable<XElement> ConvertDbToXml(Property property, IDataTypeService dataTypeService, ILocalizationService localizationService, bool published);
XNode ConvertDbToXml(PropertyType propertyType, object value, IDataTypeService dataTypeService);
string ConvertDbToString(PropertyType propertyType, object value, IDataTypeService dataTypeService);
}
}
@@ -1,25 +0,0 @@
using System.Collections.Generic;
using Umbraco.Core.Composing;
namespace Umbraco.Core.PropertyEditors
{
public interface IParameterEditor : IDiscoverable
{
/// <summary>
/// Gets the unique identifier of the editor.
/// </summary>
string Alias { get; }
/// <summary>
/// Gets the name of the editor.
/// </summary>
string Name { get; }
/// <summary>
/// Allows a parameter editor to be re-used based on the configuration specified. FIXME WTF?!
/// </summary>
IDictionary<string, object> Configuration { get; }
IValueEditor ValueEditor { get; }
}
}
@@ -1,104 +0,0 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Basic definition of a macro parameter editor
/// </summary>
public class ParameterEditor : IParameterEditor
{
private readonly ParameterEditorAttribute _attribute;
private ParameterValueEditor _valueEditor;
private ParameterValueEditor _valueEditorAssigned;
/// <summary>
/// The constructor will setup the property editor based on the attribute if one is found
/// </summary>
public ParameterEditor()
{
Configuration = new Dictionary<string, object>();
// fixme ParameterEditorAttribute is AllowMultiple
// then how can this ever make sense?
// only DropDownMultiplePropertyEditor has multiple [ParameterEditor]
// is exactly the same in v7 now
// makes no sense at all?!
// assign properties based on the attribute, if it is found
_attribute = GetType().GetCustomAttribute<ParameterEditorAttribute>(false);
if (_attribute == null) return;
Alias = _attribute.Alias;
Name = _attribute.Name;
}
/// <summary>
/// The id of the property editor
/// </summary>
[JsonProperty("alias", Required = Required.Always)]
public string Alias { get; internal set; }
/// <summary>
/// The name of the property editor
/// </summary>
[JsonProperty("name", Required = Required.Always)]
public string Name { get; internal set; }
/// <summary>
/// Allows a parameter editor to be re-used based on the configuration specified.
/// </summary>
[JsonProperty("config")]
public IDictionary<string, object> Configuration { get; set; }
/// <summary>
/// Gets or sets the value editor.
/// </summary>
/// <remarks>
/// <para>If an instance of a value editor is assigned to the property,
/// then this instance is returned when getting the property value. Otherwise, a
/// new instance is created by CreateValueEditor.</para>
/// <para>The instance created by CreateValueEditor is not cached, i.e.
/// a new instance is created each time the property value is retrieved.</para>
/// <para>The property is marked as a Json property with ObjectCreationHandling
/// set to Replace in order to prevent the Json deserializer to retrieve the
/// value of the property before setting it.</para>
/// </remarks>
[JsonProperty("editor")]
public ParameterValueEditor ValueEditor
{
get => _valueEditor ?? (_valueEditor = CreateValueEditor());
set
{
_valueEditorAssigned = value;
_valueEditor = null;
}
}
[JsonIgnore]
IValueEditor IParameterEditor.ValueEditor => ValueEditor; // fixme - because we must, but - bah
/// <summary>
/// Creates a value editor instance
/// </summary>
/// <returns></returns>
protected virtual ParameterValueEditor CreateValueEditor()
{
// handle assigned editor
if (_valueEditorAssigned != null)
return _valueEditorAssigned;
// create a new editor
var editor = new ParameterValueEditor();
var view = _attribute?.View;
if (string.IsNullOrWhiteSpace(view))
throw new InvalidOperationException("The editor does not specify a view.");
editor.View = view;
return editor;
}
}
}
@@ -1,30 +0,0 @@
using System;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Marks a class that represents a data editor.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] // fixme allow multiple?!
public sealed class ParameterEditorAttribute : DataEditorAttribute
{
/// <summary>
/// Initializes a new instance of the <see cref="ParameterEditorAttribute"/> class.
/// </summary>
/// <param name="alias">The unique identifier of the editor.</param>
/// <param name="name">The friendly name of the editor.</param>
public ParameterEditorAttribute(string alias, string name)
: this(alias, name, NullView)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="ParameterEditorAttribute"/> class.
/// </summary>
/// <param name="alias">The unique identifier of the editor.</param>
/// <param name="name">The friendly name of the editor.</param>
/// <param name="view">The view to use to render the editor.</param>
public ParameterEditorAttribute(string alias, string name, string view)
: base(alias, name, view)
{ }
}
}
@@ -4,81 +4,17 @@ using Umbraco.Core.Composing;
namespace Umbraco.Core.PropertyEditors
{
// fixme - now
// this collection is maintained but never used - yes! never injected,
// but Current.ParameterEditors is used
// - in MacroMapperProfile
// - in editMacro.aspx
// this is providing parameter editors for macros
// what's an IParameterEditor?
//
// fixme - now
// - also, grid editor
// - sort out the editors hierarchy
// - then prevalues!
//
// namespace: Umbraco.Core.DataEditors
// .Validators
// .Editors
// .ValueConverters
//
// IDataEditor
// .Alias (unique identifier)
// .Name
// .IsPropertyValueEditor
// .IsMacroParameterEditor
// .ParseConfiguration(string config) : object
//
// I <from PropertyEditor>
// .Icon
// .Group
// .IsDeprecated
// .DefaultConfiguration : object
//
// DataEditor
// .ValueEditor : IValueEditor
// .View : string
// .ConfigurationEditor : IDataEditorConfigurationEditor
//
// IDataType
// .EditorAlias
// .DataStorage (DataStorageType.Text, .Varchar, .Int, ...)
// .Configuration : object
//
// ParameterValueEditor : IValueEditor
// .View : string
//
// PropertyValueEditor : IValueEditor
// .View : string
// .HideLabel : bool
// .ValueType (ValueTypes.Xml, .String...)
// .Validators : IPropertyValidator*
// .convert...
//
// IDataEditorConfigurationEditor
// .Fields : DataEditorConfigurationField*
// .FromEditor() - should receive an JObject - need to convert to true configuration
// .ToEditor() - in most cases, just pass the configuration object
//
// load
// read config field as string from db
// read alias field as string from db
// find data editor corresponding to alias
// not found = deserialize config as IDictionary<string, object>
// else = use editor to deserialize configuration
// PROBLEM should be a POCO not a dictionary anymore
public class ParameterEditorCollection : BuilderCollectionBase<IParameterEditor>
public class ParameterEditorCollection : BuilderCollectionBase<IDataEditor>
{
public ParameterEditorCollection(IEnumerable<IParameterEditor> items)
public ParameterEditorCollection(IEnumerable<IDataEditor> items)
: base(items)
{ }
// note: virtual so it can be mocked
public virtual IParameterEditor this[string alias]
public virtual IDataEditor this[string alias]
=> this.SingleOrDefault(x => x.Alias == alias);
public virtual bool TryGet(string alias, out IParameterEditor editor)
public virtual bool TryGet(string alias, out IDataEditor editor)
{
editor = this.FirstOrDefault(x => x.Alias == alias);
return editor != null;
@@ -6,7 +6,7 @@ using Umbraco.Core.Manifest;
namespace Umbraco.Core.PropertyEditors
{
public class ParameterEditorCollectionBuilder : LazyCollectionBuilderBase<ParameterEditorCollectionBuilder, ParameterEditorCollection, IParameterEditor>
public class ParameterEditorCollectionBuilder : LazyCollectionBuilderBase<ParameterEditorCollectionBuilder, ParameterEditorCollection, IDataEditor>
{
private readonly ManifestParser _manifestParser;
@@ -18,24 +18,11 @@ namespace Umbraco.Core.PropertyEditors
protected override ParameterEditorCollectionBuilder This => this;
protected override IEnumerable<IParameterEditor> CreateItems(params object[] args)
protected override IEnumerable<IDataEditor> CreateItems(params object[] args)
{
//return base.CreateItems(args).Union(_manifestBuilder.PropertyEditors);
// the buider's producer returns all IParameterEditor implementations
// this includes classes inheriting from both PropertyEditor and ParameterEditor
// but only some PropertyEditor inheritors are also parameter editors
//
// return items,
// that are NOT PropertyEditor OR that also have IsParameterEditor set to true
// union all manifest's parameter editors
// union all manifest's property editors that are ALSO parameter editors
return base.CreateItems(args)
.Where(x => (x is PropertyEditor) == false || ((PropertyEditor) x).IsParameterEditor)
.Union(_manifestParser.Manifest.ParameterEditors)
.Union(_manifestParser.Manifest.PropertyEditors.Where(x => x.IsParameterEditor))
.ToList();
.Where(x => (x.Type & EditorType.MacroParameter) > 0)
.Union(_manifestParser.Manifest.ParameterEditors);
}
}
}
@@ -1,41 +0,0 @@
using Umbraco.Core.IO;
namespace Umbraco.Core.PropertyEditors
{
// fixme - can we kill this and use "ValueEditor" for both macro and all?
/// <summary>
/// Represents a value editor for macro parameters.
/// </summary>
public class ParameterValueEditor : IValueEditor
{
private string _view;
/// <summary>
/// Initializes a new instance of the <see cref="ParameterValueEditor"/> class.
/// </summary>
public ParameterValueEditor()
{ }
/// <summary>
/// Initializes a new instance of the <see cref="ParameterValueEditor"/> class.
/// </summary>
public ParameterValueEditor(string view)
: this()
{
View = view;
}
/// <summary>
/// Gets or sets the editor view.
/// </summary>
public string View
{
get => _view;
set => _view = IOHelper.ResolveVirtualUrl(value);
}
/// <inheritdoc />
public string ValueType { get; set; }
}
}
@@ -4,17 +4,17 @@ using Umbraco.Core.Composing;
namespace Umbraco.Core.PropertyEditors
{
public class PropertyEditorCollection : BuilderCollectionBase<PropertyEditor>
public class PropertyEditorCollection : BuilderCollectionBase<IConfiguredDataEditor>
{
public PropertyEditorCollection(IEnumerable<PropertyEditor> items)
public PropertyEditorCollection(IEnumerable<IConfiguredDataEditor> items)
: base(items)
{ }
// note: virtual so it can be mocked
public virtual PropertyEditor this[string alias]
public virtual IConfiguredDataEditor this[string alias]
=> this.SingleOrDefault(x => x.Alias == alias);
public virtual bool TryGet(string alias, out PropertyEditor editor)
public virtual bool TryGet(string alias, out IConfiguredDataEditor editor)
{
editor = this.FirstOrDefault(x => x.Alias == alias);
return editor != null;
@@ -6,7 +6,7 @@ using Umbraco.Core.Manifest;
namespace Umbraco.Core.PropertyEditors
{
public class PropertyEditorCollectionBuilder : LazyCollectionBuilderBase<PropertyEditorCollectionBuilder, PropertyEditorCollection, PropertyEditor>
public class PropertyEditorCollectionBuilder : LazyCollectionBuilderBase<PropertyEditorCollectionBuilder, PropertyEditorCollection, IConfiguredDataEditor>
{
private readonly ManifestParser _manifestParser;
@@ -18,9 +18,11 @@ namespace Umbraco.Core.PropertyEditors
protected override PropertyEditorCollectionBuilder This => this;
protected override IEnumerable<PropertyEditor> CreateItems(params object[] args)
protected override IEnumerable<IConfiguredDataEditor> CreateItems(params object[] args)
{
return base.CreateItems(args).Union(_manifestParser.Manifest.PropertyEditors);
return base.CreateItems(args)
.Where(x => (x.Type & EditorType.PropertyValue) > 0)
.Union(_manifestParser.Manifest.PropertyEditors);
}
}
}
@@ -1,20 +1,20 @@
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Provides extension methods for the <see cref="PropertyEditor"/> class to manage tags.
/// Provides extension methods for the <see cref="IDataEditor"/> interface to manage tags.
/// </summary>
public static class PropertyEditorTagsExtensions
{
/// <summary>
/// Determines whether an editor supports tags.
/// </summary>
public static bool IsTagsEditor(this PropertyEditor editor)
public static bool IsTagsEditor(this IDataEditor editor)
=> editor?.GetType().GetCustomAttribute<TagsPropertyEditorAttribute>(false) != null;
/// <summary>
/// Gets the tags configuration attribute of an editor.
/// </summary>
public static TagsPropertyEditorAttribute GetTagAttribute(this PropertyEditor editor)
public static TagsPropertyEditorAttribute GetTagAttribute(this IDataEditor editor)
=> editor?.GetType().GetCustomAttribute<TagsPropertyEditorAttribute>(false);
}
}
@@ -1,94 +0,0 @@
using System;
using Umbraco.Core.Exceptions;
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Marks a class that represents a value editor.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class ValueEditorAttribute : DataEditorAttribute
{
/// <summary>
/// Initializes a new instance of the <see cref="ValueEditorAttribute"/> class.
/// </summary>
/// <param name="alias">The unique identifier of the editor.</param>
/// <param name="name">The friendly name of the editor.</param>
public ValueEditorAttribute(string alias, string name)
: this(alias, name, NullView)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="ValueEditorAttribute"/> class.
/// </summary>
/// <param name="alias">The unique identifier of the editor.</param>
/// <param name="name">The friendly name of the editor.</param>
/// <param name="view">The view to use to render the editor.</param>
public ValueEditorAttribute(string alias, string name, string view)
: base(alias, name, view)
{
// defaults
ValueType = ValueTypes.String;
Icon = Constants.Icons.PropertyEditor;
Group = "common";
}
/// <summary>
/// Initializes a new instance of the <see cref="ValueEditorAttribute"/> class.
/// </summary>
/// <param name="alias">The unique identifier of the editor.</param>
/// <param name="name">The friendly name of the editor.</param>
/// <param name="view">The view to use to render the editor.</param>
/// <param name="valueType">The type of the edited value.</param>
/// <remarks>The <paramref name="valueType"/> must be a valid <see cref="ValueTypes"/> value.</remarks>
public ValueEditorAttribute(string alias, string name, string view, string valueType)
: this(alias, name, view)
{
if (string.IsNullOrWhiteSpace(valueType)) throw new ArgumentNullOrEmptyException(nameof(valueType));
if (!ValueTypes.IsValue(valueType)) throw new ArgumentOutOfRangeException(nameof(valueType), "Not a valid ValueTypes.");
ValueType = valueType;
}
/// <summary>
/// Gets or sets the type of the edited value.
/// </summary>
/// <remarks>Must be a valid <see cref="ValueTypes"/> value.</remarks>
public string ValueType { get; set; }
/// <summary>
/// Gets or sets a value indicating the editor type.
/// </summary>
public EditorType EditorType { get; set; } // fixme should be the attribute 1st ctor parameter?
public bool IsPropertyValueEditor => (EditorType & EditorType.PropertyValue) != 0;
/// <summary>
/// Gets or sets a value indicating whether the editor is a macro parameter editor.
/// </summary>
public bool IsMacroParameterEditor { get; set; } // => (EditorType & EditorType.MacroParameter) != 0;
/// <summary>
/// Gets or sets a value indicating whether the value editor is deprecated.
/// </summary>
/// <remarks>A deprecated editor does not show up in the list of available editors for a datatype,
/// unless it is the current editor for the datatype.</remarks>
public bool IsDeprecated { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the editor should be displayed without its label.
/// </summary>
public bool HideLabel { get; set; }
/// <summary>
/// Gets or sets an optional icon.
/// </summary>
/// <remarks>The icon can be used for example when presenting datatypes based upon the editor.</remarks>
public string Icon { get; set; }
/// <summary>
/// Gets or sets an optional group.
/// </summary>
/// <remarks>The group can be used for example to group the editors by category.</remarks>
public string Group { get; set; }
}
}
@@ -10,7 +10,7 @@ namespace Umbraco.Core.PropertyEditors
/// editor is available. Not to be used otherwise. Not discovered, and therefore
/// not part of the editors collection.</remarks>
[HideFromTypeFinder]
public class VoidEditor : PropertyEditor
public class VoidEditor : ConfiguredDataEditor
{
/// <summary>
/// Initializes a new instance of the <see cref="VoidEditor"/> class.
@@ -67,11 +67,11 @@ namespace Umbraco.Core.Runtime
.Add<IntegerValidator>()
.Add<DecimalValidator>();
// both are initialized with data editors, and filter them out
composition.Container.RegisterCollectionBuilder<PropertyEditorCollectionBuilder>()
.Add(factory => factory.GetInstance<TypeLoader>().GetPropertyEditors());
.Add(factory => factory.GetInstance<TypeLoader>().GetDataEditors());
composition.Container.RegisterCollectionBuilder<ParameterEditorCollectionBuilder>()
.Add(factory => factory.GetInstance<TypeLoader>().GetParameterEditors());
.Add(factory => factory.GetInstance<TypeLoader>().GetDataEditors());
// register a server registrar, by default it's the db registrar unless the dev
// has the legacy dist calls enabled - fixme - should obsolete the legacy thing
+8 -10
View File
@@ -336,7 +336,10 @@
<Compile Include="PropertyEditors\DataEditorAttribute.cs" />
<Compile Include="PropertyEditors\ConfigurationEditor.cs" />
<Compile Include="PropertyEditors\EditorType.cs" />
<Compile Include="PropertyEditors\IConfigurationEditor.cs" />
<Compile Include="PropertyEditors\IConfiguredDataEditor.cs" />
<Compile Include="PropertyEditors\IConfigureValueType.cs" />
<Compile Include="PropertyEditors\IDataEditor.cs" />
<Compile Include="PropertyEditors\ImageCropperConfiguration.cs" />
<Compile Include="PropertyEditors\PropertyEditorTagsExtensions.cs" />
<Compile Include="PropertyEditors\SliderPropertyEditorConfiguration.cs" />
@@ -513,8 +516,7 @@
<Compile Include="Manifest\ManifestValidatorConverter.cs" />
<Compile Include="Manifest\ManifestWatcher.cs" />
<Compile Include="Manifest\PackageManifest.cs" />
<Compile Include="Manifest\ParameterEditorConverter.cs" />
<Compile Include="Manifest\PropertyEditorConverter.cs" />
<Compile Include="Manifest\DataEditorConverter.cs" />
<Compile Include="Media\Exif\BitConverterEx.cs" />
<Compile Include="Media\Exif\ExifBitConverter.cs" />
<Compile Include="Media\Exif\ExifEnums.cs" />
@@ -1186,29 +1188,25 @@
<Compile Include="PropertyEditors\Validators\EmailValidator.cs" />
<Compile Include="PropertyEditors\GridEditor.cs" />
<Compile Include="PropertyEditors\Validators\IntegerValidator.cs" />
<Compile Include="PropertyEditors\IParameterEditor.cs" />
<Compile Include="PropertyEditors\IValueValidator.cs" />
<Compile Include="PropertyEditors\IPropertyValueConverter.cs" />
<Compile Include="PropertyEditors\IValueEditor.cs" />
<Compile Include="PropertyEditors\IDataValueEditor.cs" />
<Compile Include="PropertyEditors\ManifestValueValidator.cs" />
<Compile Include="PropertyEditors\ManifestValidator.cs" />
<Compile Include="PropertyEditors\ParameterEditor.cs" />
<Compile Include="PropertyEditors\ParameterEditorAttribute.cs" />
<Compile Include="PropertyEditors\DataEditor.cs" />
<Compile Include="PropertyEditors\ParameterEditorCollection.cs" />
<Compile Include="PropertyEditors\ParameterEditorCollectionBuilder.cs" />
<Compile Include="PropertyEditors\ParameterValueEditor.cs" />
<Compile Include="PropertyEditors\ConfigurationField.cs" />
<Compile Include="PropertyEditors\ConfigurationFieldAttribute.cs" />
<Compile Include="PropertyEditors\PropertyCacheLevel.cs" />
<Compile Include="PropertyEditors\PropertyEditor.cs" />
<Compile Include="PropertyEditors\ValueEditorAttribute.cs" />
<Compile Include="PropertyEditors\ConfiguredDataEditor.cs" />
<Compile Include="PropertyEditors\PropertyEditorCollection.cs" />
<Compile Include="PropertyEditors\PropertyEditorCollectionBuilder.cs" />
<Compile Include="PropertyEditors\ValueTypes.cs" />
<Compile Include="PropertyEditors\PropertyValueConverterBase.cs" />
<Compile Include="PropertyEditors\PropertyValueConverterCollection.cs" />
<Compile Include="PropertyEditors\PropertyValueConverterCollectionBuilder.cs" />
<Compile Include="PropertyEditors\ValueEditor.cs" />
<Compile Include="PropertyEditors\DataValueEditor.cs" />
<Compile Include="PropertyEditors\Validators\RegexValidator.cs" />
<Compile Include="PropertyEditors\RequiredManifestValueValidator.cs" />
<Compile Include="PropertyEditors\TagsPropertyEditorAttribute.cs" />
@@ -71,7 +71,7 @@ namespace Umbraco.Tests.Models.Mapping
base.Compose();
// create and register a fake property editor collection to return fake property editors
var editors = new PropertyEditor[] { new TextboxPropertyEditor(Mock.Of<ILogger>()), };
var editors = new ConfiguredDataEditor[] { new TextboxPropertyEditor(Mock.Of<ILogger>()), };
_editorsMock = new Mock<PropertyEditorCollection>(new object[] { editors });
_editorsMock.Setup(x => x[It.IsAny<string>()]).Returns(editors[0]);
Container.RegisterSingleton(f => _editorsMock.Object);
@@ -30,7 +30,7 @@ namespace Umbraco.Tests.Models.Mapping
}
[ValueEditor("Test.Test", "Test", "~/Test.html")]
public class TestPropertyEditor : PropertyEditor
public class TestPropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// The constructor will setup the property editor based on the attribute if one is found
@@ -48,7 +48,7 @@ namespace Umbraco.Tests.Persistence.Repositories
TemplateRepository tr;
var ctRepository = CreateRepository(scopeAccessor, out contentTypeRepository, out tr);
var editors = new PropertyEditorCollection(Enumerable.Empty<PropertyEditor>());
var editors = new PropertyEditorCollection(Enumerable.Empty<ConfiguredDataEditor>());
dtdRepository = new DataTypeRepository(scopeAccessor, cacheHelper, new Lazy<PropertyEditorCollection>(() => editors), Logger);
return ctRepository;
}
@@ -29,7 +29,7 @@ namespace Umbraco.Tests.Persistence.Repositories
{
base.Compose();
Container.RegisterSingleton(f => new PropertyEditorCollection(Enumerable.Empty<PropertyEditor>()));
Container.RegisterSingleton(f => new PropertyEditorCollection(Enumerable.Empty<ConfiguredDataEditor>()));
}
[Test]
@@ -37,7 +37,7 @@ namespace Umbraco.Tests.Persistence.Repositories
{
base.Compose();
Container.RegisterSingleton(f => new PropertyEditorCollection(Enumerable.Empty<PropertyEditor>()));
Container.RegisterSingleton(f => new PropertyEditorCollection(Enumerable.Empty<ConfiguredDataEditor>()));
}
[Test]
@@ -297,11 +297,11 @@ AnotherContentFinder
{
var types = new HashSet<TypeLoader.TypeList>();
var propEditors = new TypeLoader.TypeList(typeof (PropertyEditor), null);
var propEditors = new TypeLoader.TypeList(typeof (ConfiguredDataEditor), null);
propEditors.Add(typeof(LabelPropertyEditor));
types.Add(propEditors);
var found = types.SingleOrDefault(x => x.BaseType == typeof (PropertyEditor) && x.AttributeType == null);
var found = types.SingleOrDefault(x => x.BaseType == typeof (ConfiguredDataEditor) && x.AttributeType == null);
Assert.IsNotNull(found);
@@ -43,7 +43,7 @@ namespace Umbraco.Tests.PropertyEditors
var prop = new Property(1, new PropertyType("test", ValueStorageType.Nvarchar));
prop.SetValue(value);
var valueEditor = new ValueEditor
var valueEditor = new DataValueEditor
{
ValueType = ValueTypes.String
};
@@ -59,7 +59,7 @@ namespace Umbraco.Tests.PropertyEditors
[TestCase("DATETIME", "", null)] //test empty string for date
public void Value_Editor_Can_Convert_To_Clr_Type(string valueType, string val, object expected)
{
var valueEditor = new ValueEditor
var valueEditor = new DataValueEditor
{
ValueType = valueType
};
@@ -74,7 +74,7 @@ namespace Umbraco.Tests.PropertyEditors
[Test]
public void Value_Editor_Can_Convert_To_Decimal_Clr_Type()
{
var valueEditor = new ValueEditor
var valueEditor = new DataValueEditor
{
ValueType = ValueTypes.Decimal
};
@@ -87,7 +87,7 @@ namespace Umbraco.Tests.PropertyEditors
[Test]
public void Value_Editor_Can_Convert_To_Decimal_Clr_Type_With_Other_Separator()
{
var valueEditor = new ValueEditor
var valueEditor = new DataValueEditor
{
ValueType = ValueTypes.Decimal
};
@@ -100,7 +100,7 @@ namespace Umbraco.Tests.PropertyEditors
[Test]
public void Value_Editor_Can_Convert_To_Decimal_Clr_Type_With_Empty_String()
{
var valueEditor = new ValueEditor
var valueEditor = new DataValueEditor
{
ValueType = ValueTypes.Decimal
};
@@ -113,7 +113,7 @@ namespace Umbraco.Tests.PropertyEditors
[Test]
public void Value_Editor_Can_Convert_To_Date_Clr_Type()
{
var valueEditor = new ValueEditor
var valueEditor = new DataValueEditor
{
ValueType = ValueTypes.Date
};
@@ -133,7 +133,7 @@ namespace Umbraco.Tests.PropertyEditors
var prop = new Property(1, new PropertyType("test", ValueStorageType.Nvarchar));
prop.SetValue(val);
var valueEditor = new ValueEditor
var valueEditor = new DataValueEditor
{
ValueType = valueType
};
@@ -146,7 +146,7 @@ namespace Umbraco.Tests.PropertyEditors
public void Value_Editor_Can_Serialize_Decimal_Value()
{
var value = 12.34M;
var valueEditor = new ValueEditor
var valueEditor = new DataValueEditor
{
ValueType = ValueTypes.Decimal
};
@@ -161,7 +161,7 @@ namespace Umbraco.Tests.PropertyEditors
[Test]
public void Value_Editor_Can_Serialize_Decimal_Value_With_Empty_String()
{
var valueEditor = new ValueEditor
var valueEditor = new DataValueEditor
{
ValueType = ValueTypes.Decimal
};
@@ -177,7 +177,7 @@ namespace Umbraco.Tests.PropertyEditors
public void Value_Editor_Can_Serialize_Date_Value()
{
var now = DateTime.Now;
var valueEditor = new ValueEditor
var valueEditor = new DataValueEditor
{
ValueType = ValueTypes.Date
};
@@ -34,7 +34,7 @@ namespace Umbraco.Tests.Published
PropertyEditorCollection editors = null;
var editor = new NestedContentPropertyEditor(logger, new Lazy<PropertyEditorCollection>(() => editors));
editors = new PropertyEditorCollection(new PropertyEditor[] { editor });
editors = new PropertyEditorCollection(new ConfiguredDataEditor[] { editor });
var dataType1 = new DataType(editor)
{
@@ -19,7 +19,7 @@ namespace Umbraco.Tests.Services.Importing
public class PackageImportTests : TestWithSomeContentBase
{
[HideFromTypeFinder]
public class Editor1 : PropertyEditor
public class Editor1 : ConfiguredDataEditor
{
public Editor1(ILogger logger)
: base(logger)
@@ -29,7 +29,7 @@ namespace Umbraco.Tests.Services.Importing
}
[HideFromTypeFinder]
public class Editor2 : PropertyEditor
public class Editor2 : ConfiguredDataEditor
{
public Editor2(ILogger logger)
: base(logger)
+1 -1
View File
@@ -177,7 +177,7 @@ namespace Umbraco.Tests.TestHelpers
GetRepo<IEntityRepository>(c)));
var macroService = GetLazyService<IMacroService>(container, c => new MacroService(scopeProvider, logger, eventMessagesFactory, GetRepo<IMacroRepository>(c), GetRepo<IAuditRepository>(c)));
var packagingService = GetLazyService<IPackagingService>(container, c => new PackagingService(logger, contentService.Value, contentTypeService.Value, mediaService.Value, macroService.Value, dataTypeService.Value, fileService.Value, localizationService.Value, entityService.Value, userService.Value, scopeProvider, urlSegmentProviders, GetRepo<IAuditRepository>(c), GetRepo<IContentTypeRepository>(c), new PropertyEditorCollection(Enumerable.Empty<PropertyEditor>())));
var packagingService = GetLazyService<IPackagingService>(container, c => new PackagingService(logger, contentService.Value, contentTypeService.Value, mediaService.Value, macroService.Value, dataTypeService.Value, fileService.Value, localizationService.Value, entityService.Value, userService.Value, scopeProvider, urlSegmentProviders, GetRepo<IAuditRepository>(c), GetRepo<IContentTypeRepository>(c), new PropertyEditorCollection(Enumerable.Empty<ConfiguredDataEditor>())));
var relationService = GetLazyService<IRelationService>(container, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo<IRelationRepository>(c), GetRepo<IRelationTypeRepository>(c)));
var treeService = GetLazyService<IApplicationTreeService>(container, c => new ApplicationTreeService(logger, cache));
var tagService = GetLazyService<ITagService>(container, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo<ITagRepository>(c)));
@@ -147,7 +147,7 @@ namespace Umbraco.Web.Editors
if (dataTypeId == -1)
{
//this is a new data type, so just return the field editors with default values
return Mapper.Map<PropertyEditor, IEnumerable<DataTypeConfigurationFieldDisplay>>(propEd);
return Mapper.Map<IConfiguredDataEditor, IEnumerable<DataTypeConfigurationFieldDisplay>>(propEd);
}
//we have a data type associated
@@ -167,7 +167,7 @@ namespace Umbraco.Web.Editors
}
//these are new pre-values, so just return the field editors with default values
return Mapper.Map<PropertyEditor, IEnumerable<DataTypeConfigurationFieldDisplay>>(propEd);
return Mapper.Map<IConfiguredDataEditor, IEnumerable<DataTypeConfigurationFieldDisplay>>(propEd);
}
/// <summary>
@@ -35,7 +35,7 @@ namespace Umbraco.Web.Models.ContentEditing
/// Used internally during model mapping
/// </summary>
[IgnoreDataMember]
internal PropertyEditor PropertyEditor { get; set; }
internal IConfiguredDataEditor PropertyEditor { get; set; }
}
}
@@ -47,7 +47,7 @@ namespace Umbraco.Web.Models.ContentEditing
/// Gets or sets the property editor.
/// </summary>
[IgnoreDataMember]
internal PropertyEditor PropertyEditor { get; set; }
internal ConfiguredDataEditor PropertyEditor { get; set; }
}
}
@@ -33,7 +33,7 @@ namespace Umbraco.Web.Models.Mapping
// but, this is the ONLY place where it's assigned? it is also the only place where
// .HideLabel is used - and basically all the rest kinda never depends on config,
// but... it should?
var ve = (ValueEditor) valEditor;
var ve = (DataValueEditor) valEditor;
ve.Configuration = config;
//set the display properties after mapping
@@ -36,10 +36,16 @@ namespace Umbraco.Web.Models.Mapping
/// </summary>
public IEnumerable<DataTypeConfigurationFieldDisplay> Resolve(IDataType dataType)
{
PropertyEditor editor = null;
if (!string.IsNullOrWhiteSpace(dataType.EditorAlias) && !Current.PropertyEditors.TryGet(dataType.EditorAlias, out editor))
throw new InvalidOperationException($"Could not find a property editor with alias \"{dataType.EditorAlias}\".");
ConfiguredDataEditor editor = null;
if (!string.IsNullOrWhiteSpace(dataType.EditorAlias))
{
if (!Current.PropertyEditors.TryGet(dataType.EditorAlias, out var e1))
throw new InvalidOperationException($"Could not find a property editor with alias \"{dataType.EditorAlias}\".");
if (!(e1 is ConfiguredDataEditor e2))
throw new InvalidOperationException($"Property editor with alias \"{dataType.EditorAlias}\" is not configurable.");
editor = e2;
}
var configuration = dataType.Configuration;
Dictionary<string, object> configurationDictionary = null;
var fields = Array.Empty<DataTypeConfigurationFieldDisplay>();
@@ -23,7 +23,7 @@ namespace Umbraco.Web.Models.Mapping
var configurationDisplayResolver = new DataTypeConfigurationFieldDisplayResolver();
var databaseTypeResolver = new DatabaseTypeResolver();
CreateMap<PropertyEditor, PropertyEditorBasic>();
CreateMap<ConfiguredDataEditor, PropertyEditorBasic>();
// map the standard properties, not the values
CreateMap<ConfigurationField, DataTypeConfigurationFieldDisplay>()
@@ -36,7 +36,7 @@ namespace Umbraco.Web.Models.Mapping
Constants.DataTypes.DefaultMembersListView
};
CreateMap<PropertyEditor, DataTypeBasic>()
CreateMap<ConfiguredDataEditor, DataTypeBasic>()
.ForMember(dest => dest.Udi, opt => opt.Ignore())
.ForMember(dest => dest.HasPrevalues, opt => opt.Ignore())
.ForMember(dest => dest.IsSystemDataType, opt => opt.Ignore())
@@ -105,7 +105,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(dest => dest.Editor, opt => opt.MapFrom(src => propertyEditors[src.EditorAlias]));
//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
CreateMap<PropertyEditor, IEnumerable<DataTypeConfigurationFieldDisplay>>()
CreateMap<ConfiguredDataEditor, IEnumerable<DataTypeConfigurationFieldDisplay>>()
.ConvertUsing(src =>
{
// this is a new data type, initialize default configuration
@@ -13,8 +13,8 @@ namespace Umbraco.Web.PropertyEditors
/// as INT and we have logic in here to ensure it is formatted correctly including ensuring that the string value is published
/// in cache and not the int ID.
/// </remarks>
[ValueEditor(Constants.PropertyEditors.Aliases.CheckBoxList, "Checkbox list", "checkboxlist", Icon="icon-bulleted-list", Group="lists")]
public class CheckBoxListPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.CheckBoxList, "Checkbox list", "checkboxlist", Icon="icon-bulleted-list", Group="lists")]
public class CheckBoxListPropertyEditor : ConfiguredDataEditor
{
private readonly ILocalizedTextService _textService;
@@ -28,9 +28,9 @@ namespace Umbraco.Web.PropertyEditors
}
/// <inheritdoc />
protected override ConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService);
protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService);
/// <inheritdoc />
protected override IPropertyValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(false, Attribute);
protected override IDataValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(false, Attribute);
}
}
@@ -5,8 +5,8 @@ using Umbraco.Core.Services;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.ColorPicker, "Color Picker", "colorpicker", Icon="icon-colorpicker", Group="Pickers")]
public class ColorPickerPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.ColorPicker, "Color Picker", "colorpicker", Icon="icon-colorpicker", Group="Pickers")]
public class ColorPickerPropertyEditor : ConfiguredDataEditor
{
private readonly ILocalizedTextService _textService;
@@ -20,6 +20,6 @@ namespace Umbraco.Web.PropertyEditors
}
/// <inheritdoc />
protected override ConfigurationEditor CreateConfigurationEditor() => new ColorPickerConfigurationEditor(_textService);
protected override IConfigurationEditor CreateConfigurationEditor() => new ColorPickerConfigurationEditor(_textService);
}
}
@@ -8,14 +8,14 @@ namespace Umbraco.Web.PropertyEditors
/// <summary>
/// Content property editor that stores UDI
/// </summary>
[ValueEditor(Constants.PropertyEditors.Aliases.ContentPicker2Alias, "Content Picker", "contentpicker", ValueTypes.String, IsMacroParameterEditor = true, Group = "Pickers")]
public class ContentPicker2PropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.ContentPicker2Alias, EditorType.PropertyValue | EditorType.MacroParameter, "Content Picker", "contentpicker", ValueType = ValueTypes.String, Group = "Pickers")]
public class ContentPicker2PropertyEditor : ConfiguredDataEditor
{
public ContentPicker2PropertyEditor(ILogger logger)
: base(logger)
{ }
protected override ConfigurationEditor CreateConfigurationEditor()
protected override IConfigurationEditor CreateConfigurationEditor()
{
return new ContentPickerConfigurationEditor();
}
@@ -5,16 +5,16 @@ using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.Date, "Date", "datepicker", ValueTypes.Date, Icon="icon-calendar")]
public class DatePropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.Date, "Date", "datepicker", ValueType = ValueTypes.Date, Icon="icon-calendar")]
public class DatePropertyEditor : ConfiguredDataEditor
{
public DatePropertyEditor(ILogger logger): base(logger)
{ }
/// <inheritdoc />
protected override IPropertyValueEditor CreateValueEditor() => new DateValueEditor(Attribute);
protected override IDataValueEditor CreateValueEditor() => new DateValueEditor(Attribute);
/// <inheritdoc />
protected override ConfigurationEditor CreateConfigurationEditor() => new DateConfigurationEditor();
protected override IConfigurationEditor CreateConfigurationEditor() => new DateConfigurationEditor();
}
}
@@ -5,19 +5,29 @@ using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.DateTime, "Date/Time", "datepicker", ValueType = ValueTypes.DateTime, Icon="icon-time")]
public class DateTimePropertyEditor : PropertyEditor
/// <summary>
/// Represents a date and time property editor.
/// </summary>
[DataEditor(Constants.PropertyEditors.Aliases.DateTime, "Date/Time", "datepicker", ValueType = ValueTypes.DateTime, Icon="icon-time")]
public class DateTimePropertyEditor : ConfiguredDataEditor
{
public DateTimePropertyEditor(ILogger logger): base(logger)
/// <summary>
/// Initializes a new instance of the <see cref="DateTimePropertyEditor"/> class.
/// </summary>
/// <param name="logger"></param>
public DateTimePropertyEditor(ILogger logger)
: base(logger)
{ }
protected override IPropertyValueEditor CreateValueEditor()
/// <inheritdoc />
protected override IDataValueEditor CreateValueEditor()
{
var editor = base.CreateValueEditor();
editor.Validators.Add(new DateTimeValidator());
return editor;
}
protected override ConfigurationEditor CreateConfigurationEditor() => new DateTimeConfigurationEditor();
/// <inheritdoc />
protected override IConfigurationEditor CreateConfigurationEditor() => new DateTimeConfigurationEditor();
}
}
@@ -10,9 +10,9 @@ namespace Umbraco.Web.PropertyEditors
/// CUstom value editor so we can serialize with the correct date format (excluding time)
/// and includes the date validator
/// </summary>
internal class DateValueEditor : ValueEditor
internal class DateValueEditor : DataValueEditor
{
public DateValueEditor(ValueEditorAttribute attribute)
public DateValueEditor(DataEditorAttribute attribute)
: base(attribute)
{
Validators.Add(new DateTimeValidator());
@@ -28,6 +28,5 @@ namespace Umbraco.Web.PropertyEditors
//Dates will be formatted as yyyy-MM-dd
return date.Result.Value.ToString("yyyy-MM-dd");
}
}
}
@@ -5,30 +5,28 @@ using Umbraco.Core.PropertyEditors.Validators;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.Decimal, "Decimal", "decimal", ValueTypes.Decimal, IsMacroParameterEditor = true)]
public class DecimalPropertyEditor : PropertyEditor
/// <summary>
/// Represents a decimal property and parameter editor.
/// </summary>
[DataEditor(Constants.PropertyEditors.Aliases.Decimal, EditorType.PropertyValue | EditorType.MacroParameter, "Decimal", "decimal", ValueType = ValueTypes.Decimal)]
public class DecimalPropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// The constructor will setup the property editor based on the attribute if one is found
/// Initializes a new instance of the <see cref="DecimalPropertyEditor"/> class.
/// </summary>
public DecimalPropertyEditor(ILogger logger) : base(logger)
{
}
public DecimalPropertyEditor(ILogger logger)
: base(logger)
{ }
/// <summary>
/// Overridden to ensure that the value is validated
/// </summary>
/// <returns></returns>
protected override IPropertyValueEditor CreateValueEditor()
/// <inheritdoc />
protected override IDataValueEditor CreateValueEditor()
{
var editor = base.CreateValueEditor();
editor.Validators.Add(new DecimalValidator());
return editor;
}
protected override ConfigurationEditor CreateConfigurationEditor()
{
return new DecimalConfigurationEditor();
}
/// <inheritdoc />
protected override IConfigurationEditor CreateConfigurationEditor() => new DecimalConfigurationEditor();
}
}
@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using System.Collections.Generic;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.PropertyEditors;
@@ -13,10 +14,7 @@ namespace Umbraco.Web.PropertyEditors
/// Due to maintaining backwards compatibility this data type stores the value as a string which is a comma separated value of the
/// ids of the individual items so we have logic in here to deal with that.
/// </remarks>
[ParameterEditor("propertyTypePickerMultiple", "Name", "textbox")] // fixme multiple parameter editor attribute?!
[ParameterEditor("contentTypeMultiple", "Name", "textbox")]
[ParameterEditor("tabPickerMultiple", "Name", "textbox")]
[ValueEditor(Constants.PropertyEditors.Aliases.DropDownListMultiple, "Dropdown list multiple", "dropdown", Group = "lists", Icon="icon-bulleted-list")]
[DataEditor(Constants.PropertyEditors.Aliases.DropDownListMultiple, "Dropdown list multiple", "dropdown", Group = "lists", Icon="icon-bulleted-list")]
public class DropDownMultiplePropertyEditor : DropDownMultipleWithKeysPropertyEditor
{
/// <summary>
@@ -27,6 +25,6 @@ namespace Umbraco.Web.PropertyEditors
{ }
/// <inheritdoc />
protected override IPropertyValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(false, Attribute);
protected override IDataValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(false, Attribute);
}
}
@@ -14,7 +14,7 @@ namespace Umbraco.Web.PropertyEditors
/// Due to backwards compatibility, this editor stores the value as a CSV string listing
/// the ids of individual items.
/// </remarks>
[ValueEditor(Constants.PropertyEditors.Aliases.DropdownlistMultiplePublishKeys, "Dropdown list multiple, publish keys", "dropdown", Group = "lists", Icon = "icon-bulleted-list")]
[DataEditor(Constants.PropertyEditors.Aliases.DropdownlistMultiplePublishKeys, "Dropdown list multiple, publish keys", "dropdown", Group = "lists", Icon = "icon-bulleted-list")]
public class DropDownMultipleWithKeysPropertyEditor : DropDownPropertyEditor
{
private readonly ILocalizedTextService _textService;
@@ -29,9 +29,9 @@ namespace Umbraco.Web.PropertyEditors
}
/// <inheritdoc />
protected override IPropertyValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(true, Attribute);
protected override IDataValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(true, Attribute);
/// <inheritdoc />
protected override ConfigurationEditor CreateConfigurationEditor() => new DropDownMultipleConfigurationEditor(_textService);
protected override IConfigurationEditor CreateConfigurationEditor() => new DropDownMultipleConfigurationEditor(_textService);
}
}
@@ -18,7 +18,7 @@ namespace Umbraco.Web.PropertyEditors
/// as INT and we have logic in here to ensure it is formatted correctly including ensuring that the string value is published
/// in cache and not the int ID.
/// </remarks>
[ValueEditor(Constants.PropertyEditors.Aliases.DropDownList, "Dropdown list", "dropdown", ValueType = ValueTypes.String, Group = "lists", Icon = "icon-indent")]
[DataEditor(Constants.PropertyEditors.Aliases.DropDownList, "Dropdown list", "dropdown", ValueType = ValueTypes.String, Group = "lists", Icon = "icon-indent")]
public class DropDownPropertyEditor : DropDownWithKeysPropertyEditor
{
/// <summary>
@@ -32,6 +32,6 @@ namespace Umbraco.Web.PropertyEditors
/// We need to override the value editor so that we can ensure the string value is published in cache and not the integer ID value.
/// </summary>
/// <returns></returns>
protected override IPropertyValueEditor CreateValueEditor() => new PublishValueValueEditor(Attribute, Logger);
protected override IDataValueEditor CreateValueEditor() => new PublishValueValueEditor(Attribute, Logger);
}
}
@@ -13,8 +13,8 @@ namespace Umbraco.Web.PropertyEditors
/// as INT and we have logic in here to ensure it is formatted correctly including ensuring that the INT ID value is published
/// in cache and not the string value.
/// </remarks>
[ValueEditor(Constants.PropertyEditors.Aliases.DropdownlistPublishKeys, "Dropdown list, publishing keys", "dropdown", ValueType = ValueTypes.Integer, Group = "lists", Icon = "icon-indent")]
public class DropDownWithKeysPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.DropdownlistPublishKeys, "Dropdown list, publishing keys", "dropdown", ValueType = ValueTypes.Integer, Group = "lists", Icon = "icon-indent")]
public class DropDownWithKeysPropertyEditor : ConfiguredDataEditor
{
private readonly ILocalizedTextService _textService;
@@ -31,6 +31,6 @@ namespace Umbraco.Web.PropertyEditors
/// Return a custom pre-value editor
/// </summary>
/// <returns></returns>
protected override ConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService);
protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService);
}
}
@@ -5,8 +5,8 @@ using Umbraco.Core.PropertyEditors.Validators;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.EmailAddress, "Email address", "email", Icon="icon-message")]
public class EmailAddressPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.EmailAddress, "Email address", "email", Icon="icon-message")]
public class EmailAddressPropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// The constructor will setup the property editor based on the attribute if one is found
@@ -15,7 +15,7 @@ namespace Umbraco.Web.PropertyEditors
{
}
protected override IPropertyValueEditor CreateValueEditor()
protected override IDataValueEditor CreateValueEditor()
{
var editor = base.CreateValueEditor();
//add an email address validator
@@ -23,7 +23,7 @@ namespace Umbraco.Web.PropertyEditors
return editor;
}
protected override ConfigurationEditor CreateConfigurationEditor()
protected override IConfigurationEditor CreateConfigurationEditor()
{
return new EmailAddressConfigurationEditor();
}
@@ -10,8 +10,8 @@ using Umbraco.Core.Services;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.UploadField, "File upload", "fileupload", Icon = "icon-download-alt", Group = "media")]
public class FileUploadPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.UploadField, "File upload", "fileupload", Icon = "icon-download-alt", Group = "media")]
public class FileUploadPropertyEditor : ConfiguredDataEditor
{
private readonly MediaFileSystem _mediaFileSystem;
@@ -25,7 +25,7 @@ namespace Umbraco.Web.PropertyEditors
/// Creates the corresponding property value editor.
/// </summary>
/// <returns>The corresponding property value editor.</returns>
protected override IPropertyValueEditor CreateValueEditor()
protected override IDataValueEditor CreateValueEditor()
{
var editor = new FileUploadPropertyValueEditor(Attribute, _mediaFileSystem);
editor.Validators.Add(new UploadFileTypeValidator());
@@ -12,11 +12,11 @@ namespace Umbraco.Web.PropertyEditors
/// <summary>
/// The value editor for the file upload property editor.
/// </summary>
internal class FileUploadPropertyValueEditor : ValueEditor
internal class FileUploadPropertyValueEditor : DataValueEditor
{
private readonly MediaFileSystem _mediaFileSystem;
public FileUploadPropertyValueEditor(ValueEditorAttribute attribute, MediaFileSystem mediaFileSystem)
public FileUploadPropertyValueEditor(DataEditorAttribute attribute, MediaFileSystem mediaFileSystem)
: base(attribute)
{
_mediaFileSystem = mediaFileSystem ?? throw new ArgumentNullException(nameof(mediaFileSystem));
@@ -15,8 +15,11 @@ namespace Umbraco.Web.PropertyEditors
{
using Examine = global::Examine;
[ValueEditor(Constants.PropertyEditors.Aliases.Grid, "Grid layout", "grid", HideLabel = true, IsMacroParameterEditor = false, ValueType = ValueTypes.Json, Group="rich content", Icon="icon-layout")]
public class GridPropertyEditor : PropertyEditor
/// <summary>
/// Represents a grid property and parameter editor.
/// </summary>
[DataEditor(Constants.PropertyEditors.Aliases.Grid, "Grid layout", "grid", HideLabel = true, ValueType = ValueTypes.Json, Group="rich content", Icon="icon-layout")]
public class GridPropertyEditor : ConfiguredDataEditor
{
public GridPropertyEditor(ILogger logger)
: base(logger)
@@ -109,13 +112,13 @@ namespace Umbraco.Web.PropertyEditors
/// Overridden to ensure that the value is validated
/// </summary>
/// <returns></returns>
protected override IPropertyValueEditor CreateValueEditor() => new GridPropertyValueEditor(Attribute);
protected override IDataValueEditor CreateValueEditor() => new GridPropertyValueEditor(Attribute);
protected override ConfigurationEditor CreateConfigurationEditor() => new GridConfigurationEditor();
protected override IConfigurationEditor CreateConfigurationEditor() => new GridConfigurationEditor();
internal class GridPropertyValueEditor : ValueEditor
internal class GridPropertyValueEditor : DataValueEditor
{
public GridPropertyValueEditor(ValueEditorAttribute attribute)
public GridPropertyValueEditor(DataEditorAttribute attribute)
: base(attribute)
{ }
}
@@ -14,8 +14,11 @@ using Umbraco.Core.Services;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.ImageCropper, "Image Cropper", "imagecropper", ValueType = ValueTypes.Json, HideLabel = false, Group="media", Icon="icon-crop")]
public class ImageCropperPropertyEditor : PropertyEditor
/// <summary>
/// Represents an image cropper property editor.
/// </summary>
[DataEditor(Constants.PropertyEditors.Aliases.ImageCropper, "Image Cropper", "imagecropper", ValueType = ValueTypes.Json, HideLabel = false, Group="media", Icon="icon-crop")]
public class ImageCropperPropertyEditor : ConfiguredDataEditor
{
private readonly MediaFileSystem _mediaFileSystem;
private readonly UploadAutoFillProperties _autoFillProperties;
@@ -36,13 +39,13 @@ namespace Umbraco.Web.PropertyEditors
/// Creates the corresponding property value editor.
/// </summary>
/// <returns>The corresponding property value editor.</returns>
protected override IPropertyValueEditor CreateValueEditor() => new ImageCropperPropertyValueEditor(Attribute, Logger, _mediaFileSystem);
protected override IDataValueEditor CreateValueEditor() => new ImageCropperPropertyValueEditor(Attribute, Logger, _mediaFileSystem);
/// <summary>
/// Creates the corresponding preValue editor.
/// </summary>
/// <returns>The corresponding preValue editor.</returns>
protected override ConfigurationEditor CreateConfigurationEditor() => new ImageCropperConfigurationEditor();
protected override IConfigurationEditor CreateConfigurationEditor() => new ImageCropperConfigurationEditor();
/// <summary>
/// Gets a value indicating whether a property is an image cropper field.
@@ -16,12 +16,12 @@ namespace Umbraco.Web.PropertyEditors
/// <summary>
/// The value editor for the image cropper property editor.
/// </summary>
internal class ImageCropperPropertyValueEditor : ValueEditor // fixme core vs web?
internal class ImageCropperPropertyValueEditor : DataValueEditor // fixme core vs web?
{
private readonly ILogger _logger;
private readonly MediaFileSystem _mediaFileSystem;
public ImageCropperPropertyValueEditor(ValueEditorAttribute attribute, ILogger logger, MediaFileSystem mediaFileSystem)
public ImageCropperPropertyValueEditor(DataEditorAttribute attribute, ILogger logger, MediaFileSystem mediaFileSystem)
: base(attribute)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
@@ -5,15 +5,18 @@ using Umbraco.Core.PropertyEditors.Validators;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.Integer, "Numeric", "integer", IsMacroParameterEditor = true, ValueType = ValueTypes.Integer)]
public class IntegerPropertyEditor : PropertyEditor
/// <summary>
/// Represents an integer property and parameter editor.
/// </summary>
[DataEditor(Constants.PropertyEditors.Aliases.Integer, EditorType.PropertyValue | EditorType.MacroParameter, "Numeric", "integer", ValueType = ValueTypes.Integer)]
public class IntegerPropertyEditor : ConfiguredDataEditor
{
public IntegerPropertyEditor(ILogger logger)
: base(logger)
{ }
/// <inheritdoc />
protected override IPropertyValueEditor CreateValueEditor()
protected override IDataValueEditor CreateValueEditor()
{
var editor = base.CreateValueEditor();
editor.Validators.Add(new IntegerValidator()); // ensure the value is validated
@@ -21,9 +24,6 @@ namespace Umbraco.Web.PropertyEditors
}
/// <inheritdoc />
protected override ConfigurationEditor CreateConfigurationEditor()
{
return new IntegerConfigurationEditor();
}
protected override IConfigurationEditor CreateConfigurationEditor() => new IntegerConfigurationEditor();
}
}
@@ -7,8 +7,8 @@ namespace Umbraco.Web.PropertyEditors
/// <summary>
/// Represents a property editor for label properties.
/// </summary>
[ValueEditor(Constants.PropertyEditors.Aliases.NoEdit, "Label", "readonlyvalue", Icon = "icon-readonly")]
public class LabelPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.NoEdit, "Label", "readonlyvalue", Icon = "icon-readonly")]
public class LabelPropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// Initializes a new instance of the <see cref="LabelPropertyEditor"/> class.
@@ -18,15 +18,15 @@ namespace Umbraco.Web.PropertyEditors
{ }
/// <inheritdoc />
protected override IPropertyValueEditor CreateValueEditor() => new LabelPropertyValueEditor(Attribute);
protected override IDataValueEditor CreateValueEditor() => new LabelPropertyValueEditor(Attribute);
/// <inheritdoc />
protected override ConfigurationEditor CreateConfigurationEditor() => new LabelConfigurationEditor();
protected override IConfigurationEditor CreateConfigurationEditor() => new LabelConfigurationEditor();
// provides the property value editor
internal class LabelPropertyValueEditor : ValueEditor
internal class LabelPropertyValueEditor : DataValueEditor
{
public LabelPropertyValueEditor(ValueEditorAttribute attribute)
public LabelPropertyValueEditor(DataEditorAttribute attribute)
: base(attribute)
{ }
@@ -8,8 +8,8 @@ namespace Umbraco.Web.PropertyEditors
/// <summary>
/// Represents a list-view editor.
/// </summary>
[ValueEditor(Constants.PropertyEditors.Aliases.ListView, "List view", "listview", HideLabel = true, Group = "lists", Icon = "icon-item-arrangement")]
public class ListViewPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.ListView, "List view", "listview", HideLabel = true, Group = "lists", Icon = "icon-item-arrangement")]
public class ListViewPropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// Initializes a new instance of the <see cref="ListViewPropertyEditor"/> class.
@@ -20,6 +20,6 @@ namespace Umbraco.Web.PropertyEditors
{ }
/// <inheritdoc />
protected override ConfigurationEditor CreateConfigurationEditor() => new ListViewConfigurationEditor();
protected override IConfigurationEditor CreateConfigurationEditor() => new ListViewConfigurationEditor();
}
}
@@ -5,16 +5,13 @@ using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
// fixme - if deprecated, what's the alternative?
[ValueEditor(Constants.PropertyEditors.Aliases.MacroContainer, "(Obsolete) Macro Picker", "macrocontainer", ValueType = ValueTypes.Text, Group="rich content", Icon="icon-settings-alt", IsDeprecated = true)]
public class MacroContainerPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.MacroContainer, "(Obsolete) Macro Picker", "macrocontainer", ValueType = ValueTypes.Text, Group="rich content", Icon="icon-settings-alt", IsDeprecated = true)]
public class MacroContainerPropertyEditor : ConfiguredDataEditor
{
public MacroContainerPropertyEditor(ILogger logger)
: base(logger)
{ }
protected override ConfigurationEditor CreateConfigurationEditor()
{
return new MacroContainerConfigurationEditor();
}
protected override IConfigurationEditor CreateConfigurationEditor() => new MacroContainerConfigurationEditor();
}
}
@@ -7,8 +7,8 @@ namespace Umbraco.Web.PropertyEditors
/// <summary>
/// Represents a markdown editor.
/// </summary>
[ValueEditor(Constants.PropertyEditors.Aliases.MarkdownEditor, "Markdown editor", "markdowneditor", ValueType = ValueTypes.Text, Icon="icon-code", Group="rich content")]
public class MarkdownPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.MarkdownEditor, "Markdown editor", "markdowneditor", ValueType = ValueTypes.Text, Icon="icon-code", Group="rich content")]
public class MarkdownPropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// Initializes a new instance of the <see cref="MarkdownPropertyEditor"/> class.
@@ -18,9 +18,6 @@ namespace Umbraco.Web.PropertyEditors
{ }
/// <inheritdoc />
protected override ConfigurationEditor CreateConfigurationEditor()
{
return new MarkdownConfigurationEditor();
}
protected override IConfigurationEditor CreateConfigurationEditor() => new MarkdownConfigurationEditor();
}
}
@@ -1,20 +1,23 @@
using System.Collections.Generic;
using Umbraco.Core;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
/// <summary>
/// Media picker property editors that stores UDI
/// Represents a media picker property editor.
/// </summary>
[ValueEditor(Constants.PropertyEditors.Aliases.MediaPicker2, "Media Picker", "mediapicker", ValueTypes.Text, IsMacroParameterEditor = true, Group = "media", Icon = "icon-picture")]
public class MediaPicker2PropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.MediaPicker2, EditorType.PropertyValue | EditorType.MacroParameter, "mediapicker", ValueTypes.Text, Group = "media", Icon = "icon-picture")]
public class MediaPicker2PropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// Initializes a new instance of the <see cref="MediaPicker2PropertyEditor"/> class.
/// </summary>
public MediaPicker2PropertyEditor(ILogger logger)
: base(logger)
{ }
protected override ConfigurationEditor CreateConfigurationEditor() => new MediaPickerConfigurationEditor();
/// <inheritdoc />
protected override IConfigurationEditor CreateConfigurationEditor() => new MediaPickerConfigurationEditor();
}
}
@@ -1,22 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.MemberGroupPicker, "Member Group Picker", "membergrouppicker", Group="People", Icon="icon-users")]
public class MemberGroupPickerPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.MemberGroupPicker, "Member Group Picker", "membergrouppicker", Group="People", Icon="icon-users")]
public class MemberGroupPickerPropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// The constructor will setup the property editor based on the attribute if one is found
/// </summary>
public MemberGroupPickerPropertyEditor(ILogger logger) : base(logger)
{
}
public MemberGroupPickerPropertyEditor(ILogger logger)
: base(logger)
{ }
}
}
@@ -4,13 +4,13 @@ using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.MemberPicker2, "Member Picker", "memberpicker", ValueTypes.String, Group = "People", Icon = "icon-user")]
public class MemberPicker2PropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.MemberPicker2, "Member Picker", "memberpicker", ValueType = ValueTypes.String, Group = "People", Icon = "icon-user")]
public class MemberPicker2PropertyEditor : ConfiguredDataEditor
{
public MemberPicker2PropertyEditor(ILogger logger)
: base(logger)
{ }
protected override ConfigurationEditor CreateConfigurationEditor() => new MemberPickerConfiguration();
protected override IConfigurationEditor CreateConfigurationEditor() => new MemberPickerConfiguration();
}
}
@@ -4,13 +4,13 @@ using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.MultiNodeTreePicker2, "Multinode Treepicker", "contentpicker", ValueTypes.Text, Group = "pickers", Icon = "icon-page-add")]
public class MultiNodeTreePicker2PropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.MultiNodeTreePicker2, "Multinode Treepicker", "contentpicker", ValueType = ValueTypes.Text, Group = "pickers", Icon = "icon-page-add")]
public class MultiNodeTreePicker2PropertyEditor : ConfiguredDataEditor
{
public MultiNodeTreePicker2PropertyEditor(ILogger logger)
: base(logger)
{ }
protected override ConfigurationEditor CreateConfigurationEditor() => new MultiNodePickerConfigurationEditor();
protected override IConfigurationEditor CreateConfigurationEditor() => new MultiNodePickerConfigurationEditor();
}
}
@@ -10,25 +10,31 @@ using Umbraco.Core.Services;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.MultipleTextstring, "Repeatable textstrings", "multipletextbox", ValueType = ValueTypes.Text, Icon="icon-ordered-list", Group="lists")]
public class MultipleTextStringPropertyEditor : PropertyEditor
/// <summary>
/// Represents a multiple text string property editor.
/// </summary>
[DataEditor(Constants.PropertyEditors.Aliases.MultipleTextstring, "Repeatable textstrings", "multipletextbox", ValueType = ValueTypes.Text, Icon="icon-ordered-list", Group="lists")]
public class MultipleTextStringPropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// The constructor will setup the property editor based on the attribute if one is found
/// Initializes a new instance of the <see cref="MultipleTextStringPropertyEditor"/> class.
/// </summary>
public MultipleTextStringPropertyEditor(ILogger logger) : base(logger)
public MultipleTextStringPropertyEditor(ILogger logger)
: base(logger)
{ }
protected override IPropertyValueEditor CreateValueEditor() => new MultipleTextStringPropertyValueEditor(Attribute);
/// <inheritdoc />
protected override IDataValueEditor CreateValueEditor() => new MultipleTextStringPropertyValueEditor(Attribute);
protected override ConfigurationEditor CreateConfigurationEditor() => new MultipleTextStringConfigurationEditor();
/// <inheritdoc />
protected override IConfigurationEditor CreateConfigurationEditor() => new MultipleTextStringConfigurationEditor();
/// <summary>
/// Custom value editor so we can format the value for the editor and the database
/// </summary>
internal class MultipleTextStringPropertyValueEditor : ValueEditor
internal class MultipleTextStringPropertyValueEditor : DataValueEditor
{
public MultipleTextStringPropertyValueEditor(ValueEditorAttribute attribute)
public MultipleTextStringPropertyValueEditor(DataEditorAttribute attribute)
: base(attribute)
{ }
@@ -15,8 +15,11 @@ using Umbraco.Core.Services;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.NestedContent, "Nested Content", "nestedcontent", ValueType = "JSON", Group = "lists", Icon = "icon-thumbnail-list")]
public class NestedContentPropertyEditor : PropertyEditor
/// <summary>
/// Represents a nested content property editor.
/// </summary>
[DataEditor(Constants.PropertyEditors.Aliases.NestedContent, "Nested Content", "nestedcontent", ValueType = "JSON", Group = "lists", Icon = "icon-thumbnail-list")]
public class NestedContentPropertyEditor : ConfiguredDataEditor
{
private readonly Lazy<PropertyEditorCollection> _propertyEditors;
@@ -41,19 +44,19 @@ namespace Umbraco.Web.PropertyEditors
#region Pre Value Editor
protected override ConfigurationEditor CreateConfigurationEditor() => new NestedContentConfigurationEditor();
protected override IConfigurationEditor CreateConfigurationEditor() => new NestedContentConfigurationEditor();
#endregion
#region Value Editor
protected override IPropertyValueEditor CreateValueEditor() => new NestedContentPropertyValueEditor(Attribute, PropertyEditors);
protected override IDataValueEditor CreateValueEditor() => new NestedContentPropertyValueEditor(Attribute, PropertyEditors);
internal class NestedContentPropertyValueEditor : ValueEditor
internal class NestedContentPropertyValueEditor : DataValueEditor
{
private readonly PropertyEditorCollection _propertyEditors;
public NestedContentPropertyValueEditor(ValueEditorAttribute attribute, PropertyEditorCollection propertyEditors)
public NestedContentPropertyValueEditor(DataEditorAttribute attribute, PropertyEditorCollection propertyEditors)
: base(attribute)
{
_propertyEditors = propertyEditors;
@@ -1,20 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors.ParameterEditors
{
[ParameterEditor("contentType", "Content Type Picker", "entitypicker")]
public class ContentTypeParameterEditor : ParameterEditor
/// <summary>
/// Represents a content type parameter editor.
/// </summary>
[DataEditor("contentType", EditorType.MacroParameter, "Content Type Picker", "entitypicker")]
public class ContentTypeParameterEditor : DataEditor
{
/// <summary>
/// Initializes a new instance of the <see cref="ContentTypeParameterEditor"/> class.
/// </summary>
public ContentTypeParameterEditor()
{
Configuration.Add("multiple", "0");
Configuration.Add("entityType", "DocumentType");
// configure
DefaultConfiguration.Add("multiple", false);
DefaultConfiguration.Add("entityType", "DocumentType");
}
}
}
@@ -2,13 +2,14 @@
namespace Umbraco.Web.PropertyEditors.ParameterEditors
{
[ParameterEditor("contentTypeMultiple", "Multiple Content Type Picker", "entitypicker")]
public class MultipleContentTypeParameterEditor : ParameterEditor
[DataEditor("contentTypeMultiple", EditorType.MacroParameter, "Multiple Content Type Picker", "entitypicker")]
public class MultipleContentTypeParameterEditor : DataEditor
{
public MultipleContentTypeParameterEditor()
{
Configuration.Add("multiple", "1");
Configuration.Add("entityType", "DocumentType");
// configure
DefaultConfiguration.Add("multiple", true);
DefaultConfiguration.Add("entityType", "DocumentType");
}
}
}
@@ -2,15 +2,16 @@
namespace Umbraco.Web.PropertyEditors.ParameterEditors
{
[ParameterEditor("tabPickerMultiple", "Multiple Tab Picker", "entitypicker")]
public class MultiplePropertyGroupParameterEditor : ParameterEditor
[DataEditor("tabPickerMultiple", EditorType.MacroParameter, "Multiple Tab Picker", "entitypicker")]
public class MultiplePropertyGroupParameterEditor : DataEditor
{
public MultiplePropertyGroupParameterEditor()
{
Configuration.Add("multiple", "1");
Configuration.Add("entityType", "PropertyGroup");
//don't publish the id for a property group, publish it's alias (which is actually just it's lower cased name)
Configuration.Add("publishBy", "alias");
// configure
DefaultConfiguration.Add("multiple", true);
DefaultConfiguration.Add("entityType", "PropertyGroup");
//don't publish the id for a property group, publish its alias, which is actually just its lower cased name
DefaultConfiguration.Add("publishBy", "alias");
}
}
}
@@ -2,15 +2,16 @@
namespace Umbraco.Web.PropertyEditors.ParameterEditors
{
[ParameterEditor("propertyTypePickerMultiple", "Multiple Property Type Picker", "entitypicker")]
public class MultiplePropertyTypeParameterEditor : ParameterEditor
[DataEditor("propertyTypePickerMultiple", EditorType.MacroParameter, "Multiple Property Type Picker", "entitypicker")]
public class MultiplePropertyTypeParameterEditor : DataEditor
{
public MultiplePropertyTypeParameterEditor()
{
Configuration.Add("multiple", "1");
Configuration.Add("entityType", "PropertyType");
//don't publish the id for a property type, publish it's alias
Configuration.Add("publishBy", "alias");
// configure
DefaultConfiguration.Add("multiple", "1");
DefaultConfiguration.Add("entityType", "PropertyType");
//don't publish the id for a property type, publish its alias
DefaultConfiguration.Add("publishBy", "alias");
}
}
}
@@ -2,15 +2,16 @@
namespace Umbraco.Web.PropertyEditors.ParameterEditors
{
[ParameterEditor("tabPicker", "Tab Picker", "entitypicker")]
public class PropertyGroupParameterEditor : ParameterEditor
[DataEditor("tabPicker", EditorType.MacroParameter, "Tab Picker", "entitypicker")]
public class PropertyGroupParameterEditor : DataEditor
{
public PropertyGroupParameterEditor()
{
Configuration.Add("multiple", "0");
Configuration.Add("entityType", "PropertyGroup");
// configure
DefaultConfiguration.Add("multiple", "0");
DefaultConfiguration.Add("entityType", "PropertyGroup");
//don't publish the id for a property group, publish it's alias (which is actually just it's lower cased name)
Configuration.Add("publishBy", "alias");
DefaultConfiguration.Add("publishBy", "alias");
}
}
}
@@ -2,15 +2,16 @@
namespace Umbraco.Web.PropertyEditors.ParameterEditors
{
[ParameterEditor("propertyTypePicker", "Property Type Picker", "entitypicker")]
public class PropertyTypeParameterEditor : ParameterEditor
[DataEditor("propertyTypePicker", EditorType.MacroParameter, "Property Type Picker", "entitypicker")]
public class PropertyTypeParameterEditor : DataEditor
{
public PropertyTypeParameterEditor()
{
Configuration.Add("multiple", "0");
Configuration.Add("entityType", "PropertyType");
//don't publish the id for a property type, publish it's alias
Configuration.Add("publishBy", "alias");
// configure
DefaultConfiguration.Add("multiple", "0");
DefaultConfiguration.Add("entityType", "PropertyType");
//don't publish the id for a property type, publish its alias
DefaultConfiguration.Add("publishBy", "alias");
}
}
}
@@ -16,11 +16,11 @@ namespace Umbraco.Web.PropertyEditors
/// This is required for legacy/backwards compatibility, otherwise we'd just store the string version and cache the string version without
/// needing additional lookups.
/// </remarks>
internal class PublishValueValueEditor : ValueEditor
internal class PublishValueValueEditor : DataValueEditor
{
private readonly ILogger _logger;
internal PublishValueValueEditor(ValueEditorAttribute attribute, ILogger logger)
internal PublishValueValueEditor(DataEditorAttribute attribute, ILogger logger)
: base(attribute)
{
_logger = logger;
@@ -21,13 +21,13 @@ namespace Umbraco.Web.PropertyEditors
{
private readonly bool _publishIds;
internal PublishValuesMultipleValueEditor(bool publishIds, ILogger logger, ValueEditorAttribute attribute)
internal PublishValuesMultipleValueEditor(bool publishIds, ILogger logger, DataEditorAttribute attribute)
: base(attribute, logger)
{
_publishIds = publishIds;
}
public PublishValuesMultipleValueEditor(bool publishIds, ValueEditorAttribute attribute)
public PublishValuesMultipleValueEditor(bool publishIds, DataEditorAttribute attribute)
: this(publishIds, Current.Logger, attribute)
{ }
@@ -13,14 +13,14 @@ namespace Umbraco.Web.PropertyEditors
/// as INT and we have logic in here to ensure it is formatted correctly including ensuring that the INT ID value is published
/// in cache and not the string value.
/// </remarks>
[ValueEditor(Constants.PropertyEditors.Aliases.RadioButtonList, "Radio button list", "radiobuttons", ValueType = ValueTypes.Integer, Group="lists", Icon="icon-target")]
[DataEditor(Constants.PropertyEditors.Aliases.RadioButtonList, "Radio button list", "radiobuttons", ValueType = ValueTypes.Integer, Group="lists", Icon="icon-target")]
public class RadioButtonsPropertyEditor : DropDownWithKeysPropertyEditor
{
/// <summary>
/// The constructor will setup the property editor based on the attribute if one is found
/// </summary>
public RadioButtonsPropertyEditor(ILogger logger, ILocalizedTextService textService) : base(logger, textService)
{
}
public RadioButtonsPropertyEditor(ILogger logger, ILocalizedTextService textService)
: base(logger, textService)
{ }
}
}
@@ -5,13 +5,13 @@ using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.RelatedLinks2, "Related links", "relatedlinks", ValueType = ValueTypes.Json, Icon = "icon-thumbnail-list", Group = "pickers")]
public class RelatedLinks2PropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.RelatedLinks2, "Related links", "relatedlinks", ValueType = ValueTypes.Json, Icon = "icon-thumbnail-list", Group = "pickers")]
public class RelatedLinks2PropertyEditor : ConfiguredDataEditor
{
public RelatedLinks2PropertyEditor(ILogger logger)
: base(logger)
{ }
protected override ConfigurationEditor CreateConfigurationEditor() => new RelatedLinksConfigurationEditor();
protected override IConfigurationEditor CreateConfigurationEditor() => new RelatedLinksConfigurationEditor();
}
}
@@ -9,8 +9,11 @@ using Umbraco.Core.Services;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.TinyMce, "Rich Text Editor", "rte", ValueType = ValueTypes.Text, HideLabel = false, Group="Rich Content", Icon="icon-browser-window")]
public class RichTextPropertyEditor : PropertyEditor
/// <summary>
/// Represents a rich text property editor.
/// </summary>
[DataEditor(Constants.PropertyEditors.Aliases.TinyMce, "Rich Text Editor", "rte", ValueType = ValueTypes.Text, HideLabel = false, Group="Rich Content", Icon="icon-browser-window")]
public class RichTextPropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// The constructor will setup the property editor based on the attribute if one is found
@@ -23,17 +26,17 @@ namespace Umbraco.Web.PropertyEditors
/// Create a custom value editor
/// </summary>
/// <returns></returns>
protected override IPropertyValueEditor CreateValueEditor() => new RichTextPropertyValueEditor(Attribute);
protected override IDataValueEditor CreateValueEditor() => new RichTextPropertyValueEditor(Attribute);
protected override ConfigurationEditor CreateConfigurationEditor() => new RichTextConfigurationEditor();
protected override IConfigurationEditor CreateConfigurationEditor() => new RichTextConfigurationEditor();
/// <summary>
/// A custom value editor to ensure that macro syntax is parsed when being persisted and formatted correctly for display in the editor
/// </summary>
internal class RichTextPropertyValueEditor : ValueEditor
internal class RichTextPropertyValueEditor : DataValueEditor
{
public RichTextPropertyValueEditor(ValueEditorAttribute attribute)
public RichTextPropertyValueEditor(DataEditorAttribute attribute)
: base(attribute)
{ }
@@ -7,8 +7,8 @@ namespace Umbraco.Web.PropertyEditors
/// <summary>
/// Represents a slider editor.
/// </summary>
[ValueEditor(Constants.PropertyEditors.Aliases.Slider, "Slider", "slider", Icon="icon-navigation-horizontal")]
public class SliderPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.Slider, "Slider", "slider", Icon = "icon-navigation-horizontal")]
public class SliderPropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// Initializes a new instance of the <see cref="SliderPropertyEditor"/> class.
@@ -18,7 +18,7 @@ namespace Umbraco.Web.PropertyEditors
{ }
/// <inheritdoc />
protected override ConfigurationEditor CreateConfigurationEditor()
protected override IConfigurationEditor CreateConfigurationEditor()
{
return new SliderConfigurationEditor();
}
@@ -10,9 +10,12 @@ using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
/// <summary>
/// Represents a tags property editor.
/// </summary>
[TagsPropertyEditor]
[ValueEditor(Constants.PropertyEditors.Aliases.Tags, "Tags", "tags", Icon="icon-tags")]
public class TagsPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.Tags, "Tags", "tags", Icon="icon-tags")]
public class TagsPropertyEditor : ConfiguredDataEditor
{
private readonly ManifestValidatorCollection _validators;
@@ -22,13 +25,13 @@ namespace Umbraco.Web.PropertyEditors
_validators = validators;
}
protected override IPropertyValueEditor CreateValueEditor() => new TagPropertyValueEditor(Attribute);
protected override IDataValueEditor CreateValueEditor() => new TagPropertyValueEditor(Attribute);
protected override ConfigurationEditor CreateConfigurationEditor() => new TagConfigurationEditor(_validators);
protected override IConfigurationEditor CreateConfigurationEditor() => new TagConfigurationEditor(_validators);
internal class TagPropertyValueEditor : ValueEditor
internal class TagPropertyValueEditor : DataValueEditor
{
public TagPropertyValueEditor(ValueEditorAttribute attribute)
public TagPropertyValueEditor(DataEditorAttribute attribute)
: base(attribute)
{ }
@@ -5,10 +5,10 @@ using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
/// <summary>
/// Represents a textarea editor.
/// Represents a textarea property and parameter editor.
/// </summary>
[ValueEditor(Constants.PropertyEditors.Aliases.TextboxMultiple, "Textarea", "textarea", IsMacroParameterEditor = true, ValueType = ValueTypes.Text, Icon="icon-application-window-alt")]
public class TextAreaPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.TextboxMultiple, EditorType.PropertyValue | EditorType.MacroParameter, "Textarea", "textarea", ValueType = ValueTypes.Text, Icon="icon-application-window-alt")]
public class TextAreaPropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// Initializes a new instance of the <see cref="TextAreaPropertyEditor"/> class.
@@ -18,9 +18,9 @@ namespace Umbraco.Web.PropertyEditors
{ }
/// <inheritdoc />
protected override IPropertyValueEditor CreateValueEditor() => new TextOnlyValueEditor(Attribute);
protected override IDataValueEditor CreateValueEditor() => new TextOnlyValueEditor(Attribute);
/// <inheritdoc />
protected override ConfigurationEditor CreateConfigurationEditor() => new TextAreaConfigurationEditor();
protected override IConfigurationEditor CreateConfigurationEditor() => new TextAreaConfigurationEditor();
}
}
@@ -9,9 +9,9 @@ namespace Umbraco.Web.PropertyEditors
/// Custom value editor which ensures that the value stored is just plain text and that
/// no magic json formatting occurs when translating it to and from the database values
/// </summary>
public class TextOnlyValueEditor : ValueEditor
public class TextOnlyValueEditor : DataValueEditor
{
public TextOnlyValueEditor(ValueEditorAttribute attribute)
public TextOnlyValueEditor(DataEditorAttribute attribute)
: base(attribute)
{ }
@@ -5,10 +5,10 @@ using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
/// <summary>
/// Represents a textbox editor.
/// Represents a textbox property and parameter editor.
/// </summary>
[ValueEditor(Constants.PropertyEditors.Aliases.Textbox, "Textbox", "textbox", IsMacroParameterEditor = true, Group = "Common")]
public class TextboxPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.Textbox, EditorType.PropertyValue | EditorType.MacroParameter, "Textbox", "textbox", Group = "Common")]
public class TextboxPropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// Initializes a new instance of the <see cref="TextboxPropertyEditor"/> class.
@@ -18,9 +18,9 @@ namespace Umbraco.Web.PropertyEditors
{ }
/// <inheritdoc/>
protected override IPropertyValueEditor CreateValueEditor() => new TextOnlyValueEditor(Attribute);
protected override IDataValueEditor CreateValueEditor() => new TextOnlyValueEditor(Attribute);
/// <inheritdoc/>
protected override ConfigurationEditor CreateConfigurationEditor() => new TextboxConfigurationEditor();
protected override IConfigurationEditor CreateConfigurationEditor() => new TextboxConfigurationEditor();
}
}
@@ -5,10 +5,10 @@ using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
/// <summary>
/// Represents a boolean editor.
/// Represents a boolean property and parameter editor.
/// </summary>
[ValueEditor(Constants.PropertyEditors.Aliases.Boolean, "True/False", "boolean", ValueTypes.Integer, IsMacroParameterEditor = true, Group = "Common", Icon="icon-checkbox")]
public class TrueFalsePropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.Boolean, EditorType.PropertyValue | EditorType.MacroParameter, "True/False", "boolean", ValueType = ValueTypes.Integer, Group = "Common", Icon="icon-checkbox")]
public class TrueFalsePropertyEditor : ConfiguredDataEditor
{
/// <summary>
/// Initializes a new instance of the <see cref="TrueFalsePropertyEditor"/> class.
@@ -18,9 +18,6 @@ namespace Umbraco.Web.PropertyEditors
{ }
/// <inheritdoc />
protected override ConfigurationEditor CreateConfigurationEditor()
{
return new TrueFalseConfigurationEditor();
}
protected override IConfigurationEditor CreateConfigurationEditor() => new TrueFalseConfigurationEditor();
}
}
@@ -0,0 +1,13 @@
using System.Collections.Generic;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
public class UserPickerConfiguration : ConfigurationEditor
{
public override IDictionary<string, object> DefaultConfiguration => new Dictionary<string, object>
{
{"entityType", "User"}
};
}
}
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel;
using System.Web.Mvc;
using Umbraco.Core;
using Umbraco.Core.Logging;
@@ -7,21 +6,13 @@ using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
[ValueEditor(Constants.PropertyEditors.Aliases.UserPicker, "User picker", "entitypicker", ValueTypes.Integer, Group="People", Icon="icon-user")]
public class UserPickerPropertyEditor : PropertyEditor
[DataEditor(Constants.PropertyEditors.Aliases.UserPicker, "User picker", "entitypicker", ValueType = ValueTypes.Integer, Group = "People", Icon = "icon-user")]
public class UserPickerPropertyEditor : ConfiguredDataEditor
{
public UserPickerPropertyEditor(ILogger logger)
: base(logger)
{ }
protected override ConfigurationEditor CreateConfigurationEditor() => new UserPickerConfiguration();
}
public class UserPickerConfiguration : ConfigurationEditor
{
public override IDictionary<string, object> DefaultConfiguration => new Dictionary<string, object>
{
{"entityType", "User"}
};
protected override IConfigurationEditor CreateConfigurationEditor() => new UserPickerConfiguration();
}
}
+1
View File
@@ -289,6 +289,7 @@
<Compile Include="PropertyEditors\TextOnlyValueEditor.cs" />
<Compile Include="PropertyEditors\TrueFalseConfiguration.cs" />
<Compile Include="PropertyEditors\TrueFalseConfigurationEditor.cs" />
<Compile Include="PropertyEditors\UserPickerConfiguration.cs" />
<Compile Include="PropertyEditors\ValueConverters\NestedContentManyValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\NestedContentValueConverterBase.cs" />
<Compile Include="PropertyEditors\ValueConverters\NestedContentSingleValueConverter.cs" />
@@ -177,7 +177,7 @@ namespace umbraco.cms.presentation.developer
return Convert.IsDBNull(test) ? 0 : test;
}
protected IEnumerable<IParameterEditor> GetMacroParameterEditors()
protected IEnumerable<IDataEditor> GetMacroParameterEditors()
{
// we need to show the depracated ones for backwards compatibility
// FIXME not managing deprecated here?!