Merge pull request #3414 from umbraco/temp8-remove-legacy-drop-downs

v8 - Remove legacy drop downs
This commit is contained in:
Warren Buckley
2018-10-30 15:30:49 +00:00
committed by GitHub
31 changed files with 261 additions and 623 deletions

View File

@@ -44,26 +44,6 @@ namespace Umbraco.Core
/// </summary>
public const string DateTime = "Umbraco.DateTime";
/// <summary>
/// DropDown List.
/// </summary>
public const string DropDownList = "Umbraco.DropDown";
/// <summary>
/// DropDown List, Publish Keys.
/// </summary>
public const string DropdownlistPublishKeys = "Umbraco.DropdownlistPublishingKeys";
/// <summary>
/// DropDown List Multiple.
/// </summary>
public const string DropDownListMultiple = "Umbraco.DropDownMultiple";
/// <summary>
/// DropDown List Multiple, Publish Keys.
/// </summary>
public const string DropdownlistMultiplePublishKeys = "Umbraco.DropdownlistMultiplePublishKeys";
/// <summary>
/// DropDown List.
/// </summary>

View File

@@ -117,7 +117,7 @@ namespace Umbraco.Core.Migrations.Install
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DropDownMultiple, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DropDownMultiple}", SortOrder = 2, UniqueId = new Guid("0b6a45e7-44ba-430d-9da5-4e46060b9e03"), Text = "Dropdown", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -41, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-41", SortOrder = 2, UniqueId = new Guid("5046194e-4237-453c-a547-15db3a07c4e1"), Text = "Date Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -40, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-40", SortOrder = 2, UniqueId = new Guid("bb5f57c9-ce2b-4bb9-b697-4caca783a805"), Text = "Radiobox", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -39, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-39", SortOrder = 2, UniqueId = new Guid("f38f0ac7-1d27-439c-9f3f-089cd8825a53"), Text = "Dropdown multiple", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DropDownSingle, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DropDownSingle}", SortOrder = 2, UniqueId = new Guid("f38f0ac7-1d27-439c-9f3f-089cd8825a53"), Text = "Dropdown multiple", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -37, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-37", SortOrder = 2, UniqueId = new Guid("0225af17-b302-49cb-9176-b9f35cab9c17"), Text = "Approved Color", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -36, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-36", SortOrder = 2, UniqueId = new Guid("e4d66c0f-b935-4200-81f0-025f7256b89a"), Text = "Date Picker with time", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultContentListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DefaultContentListView}", SortOrder = 2, UniqueId = new Guid("C0808DD3-8133-4E4B-8CE8-E2BEA84A96A4"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });

View File

@@ -139,6 +139,8 @@ namespace Umbraco.Core.Migrations.Upgrade
Chain<DropTaskTables>("{6A2C7C1B-A9DB-4EA9-B6AB-78E7D5B722A7}");
Chain<FixLockTablePrimaryKey>("{77874C77-93E5-4488-A404-A630907CEEF0}");
Chain<AddLogTableColumns>("{8804D8E8-FE62-4E3A-B8A2-C047C2118C38}");
Chain<DropPreValueTable>("{23275462-446E-44C7-8C2C-3B8C1127B07D}");
Chain<DropDownPropertyEditorsMigration>("{6B251841-3069-4AD5-8AE9-861F9523E8DA}");
//FINAL

View File

@@ -7,10 +7,11 @@ using NPoco;
using Umbraco.Core.Migrations.Install;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Persistence.Querying;
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
{
public class DataTypeMigration : MigrationBase
{
public DataTypeMigration(IMigrationContext context)
@@ -79,10 +80,6 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
Database.Update(dataType);
}
// drop preValues table
// FIXME keep it around for now
//Delete.Table("cmsDataTypePreValues");
}
[TableName("cmsDataTypePreValues")]

View File

@@ -0,0 +1,172 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
{
public class DropDownPropertyEditorsMigration : MigrationBase
{
public DropDownPropertyEditorsMigration(IMigrationContext context) : base(context)
{
}
public override void Migrate()
{
//need to convert the old drop down data types to use the new one
var oldDropDowns = Database.Fetch<DataTypeDto>(Sql()
.Select<DataTypeDto>()
.From<DataTypeDto>()
.Where<DataTypeDto>(x => x.EditorAlias.Contains(".DropDown")));
foreach (var dd in oldDropDowns)
{
//nothing to change if there is no config
if (dd.Configuration.IsNullOrWhiteSpace()) continue;
ValueListConfiguration config;
try
{
config = JsonConvert.DeserializeObject<ValueListConfiguration>(dd.Configuration);
}
catch (Exception ex)
{
Logger.Error<DropDownPropertyEditorsMigration>(
ex, "Invalid drop down configuration detected: \"{Configuration}\", cannot convert editor, values will be cleared",
dd.Configuration);
dd.Configuration = null;
Database.Update(dd);
continue;
}
var propDataSql = Sql().Select<PropertyDataDto>().From<PropertyDataDto>()
.InnerJoin<PropertyTypeDto>().On<PropertyTypeDto, PropertyDataDto>(x => x.Id, x => x.PropertyTypeId)
.InnerJoin<DataTypeDto>().On<DataTypeDto, PropertyTypeDto>(x => x.NodeId, x => x.DataTypeId)
.Where<PropertyTypeDto>(x => x.DataTypeId == dd.NodeId);
var propDatas = Database.Query<PropertyDataDto>(propDataSql);
var toUpdate = new List<PropertyDataDto>();
foreach (var propData in propDatas)
{
if (UpdatePropertyDataDto(propData, config))
{
//update later, we are iterating all values right now so no SQL can be run inside of this iteration (i.e. Query<T>)
toUpdate.Add(propData);
}
}
//run the property data updates
foreach (var propData in toUpdate)
{
Database.Update(propData);
}
var requiresCacheRebuild = false;
switch (dd.EditorAlias)
{
case string ea when ea.InvariantEquals("Umbraco.DropDown"):
UpdateDataType(dd, config, false);
break;
case string ea when ea.InvariantEquals("Umbraco.DropdownlistPublishingKeys"):
UpdateDataType(dd, config, false);
requiresCacheRebuild = true;
break;
case string ea when ea.InvariantEquals("Umbraco.DropDownMultiple"):
UpdateDataType(dd, config, true);
break;
case string ea when ea.InvariantEquals("Umbraco.DropdownlistMultiplePublishKeys"):
UpdateDataType(dd, config, true);
requiresCacheRebuild = true;
break;
}
if (requiresCacheRebuild)
{
//TODO: How to force rebuild the cache?
}
}
}
private void UpdateDataType(DataTypeDto dataType, ValueListConfiguration config, bool isMultiple)
{
dataType.EditorAlias = Constants.PropertyEditors.Aliases.DropDownListFlexible;
var flexConfig = new
{
multiple = isMultiple,
items = config.Items
};
dataType.DbType = ValueStorageType.Nvarchar.ToString();
dataType.Configuration = JsonConvert.SerializeObject(flexConfig);
Database.Update(dataType);
}
private bool UpdatePropertyDataDto(PropertyDataDto propData, ValueListConfiguration config)
{
//Get the INT ids stored for this property/drop down
int[] ids = null;
if (!propData.VarcharValue.IsNullOrWhiteSpace())
{
ids = ConvertStringValues(propData.VarcharValue);
}
else if (!propData.TextValue.IsNullOrWhiteSpace())
{
ids = ConvertStringValues(propData.TextValue);
}
else if (propData.IntegerValue.HasValue)
{
ids = new[] { propData.IntegerValue.Value };
}
//if there are INT ids, convert them to values based on the configured pre-values
if (ids != null && ids.Length > 0)
{
//map the ids to values
var vals = new List<string>();
var canConvert = true;
foreach (var id in ids)
{
var val = config.Items.FirstOrDefault(x => x.Id == id);
if (val != null)
vals.Add(val.Value);
else
{
Logger.Warn<DropDownPropertyEditorsMigration>(
"Could not find associated data type configuration for stored Id {DataTypeId}", id);
canConvert = false;
}
}
if (canConvert)
{
propData.VarcharValue = string.Join(",", vals);
propData.TextValue = null;
propData.IntegerValue = null;
return true;
}
}
return false;
}
private int[] ConvertStringValues(string val)
{
var splitVals = val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var intVals = splitVals
.Select(x => int.TryParse(x, out var i) ? i : int.MinValue)
.Where(x => x != int.MinValue)
.ToArray();
//only return if the number of values are the same (i.e. All INTs)
if (splitVals.Length == intVals.Length)
return intVals;
return null;
}
}
}

View File

@@ -0,0 +1,16 @@
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
{
public class DropPreValueTable : MigrationBase
{
public DropPreValueTable(IMigrationContext context) : base(context)
{
}
public override void Migrate()
{
// drop preValues table
if (TableExists("cmsDataTypePreValues"))
Delete.Table("cmsDataTypePreValues").Do();
}
}
}

View File

@@ -1,33 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.PropertyEditors.ValueConverters
{
[DefaultPropertyValueConverter]
public class DropdownListMultipleValueConverter : PropertyValueConverterBase
{
public override bool IsConverter(PublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropDownListMultiple);
public override Type GetPropertyValueType(PublishedPropertyType propertyType)
=> typeof (IEnumerable<string>);
public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
=> PropertyCacheLevel.Element;
public override object ConvertIntermediateToObject(IPublishedElement owner, PublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object source, bool preview)
{
var sourceString = (source ?? "").ToString();
if (string.IsNullOrEmpty(sourceString))
return Enumerable.Empty<string>();
var values =
sourceString.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => v.Trim());
return values;
}
}
}

View File

@@ -1,34 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.PropertyEditors.ValueConverters
{
[DefaultPropertyValueConverter]
public class DropdownListMultipleWithKeysValueConverter : PropertyValueConverterBase
{
public override bool IsConverter(PublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropdownlistMultiplePublishKeys);
public override Type GetPropertyValueType(PublishedPropertyType propertyType)
=> typeof (IEnumerable<int>);
public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
=> PropertyCacheLevel.Element;
public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview)
{
if (source == null)
return new int[] { };
var prevalueIds = source.ToString()
.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(p => p.Trim())
.Select(int.Parse)
.ToArray();
return prevalueIds;
}
}
}

View File

@@ -1,23 +0,0 @@
using System;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.PropertyEditors.ValueConverters
{
[DefaultPropertyValueConverter]
public class DropdownListValueConverter : PropertyValueConverterBase
{
public override bool IsConverter(PublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropDownList);
public override Type GetPropertyValueType(PublishedPropertyType propertyType)
=> typeof (string);
public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
=> PropertyCacheLevel.Element;
public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview)
{
return source?.ToString() ?? string.Empty;
}
}
}

View File

@@ -1,27 +0,0 @@
using System;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.PropertyEditors.ValueConverters
{
[DefaultPropertyValueConverter]
public class DropdownListWithKeysValueConverter : PropertyValueConverterBase
{
public override bool IsConverter(PublishedPropertyType propertyType)
=> propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DropdownlistPublishKeys);
public override Type GetPropertyValueType(PublishedPropertyType propertyType)
=> typeof (int);
public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType)
=> PropertyCacheLevel.Element;
public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview)
{
var intAttempt = source.TryConvertTo<int>();
if (intAttempt.Success)
return intAttempt.Result;
return null;
}
}
}

View File

@@ -357,6 +357,8 @@
<Compile Include="Migrations\Upgrade\V_8_0_0\AddVariationTables1A.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\AddVariationTables2.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypeMigration.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\DropDownPropertyEditorsMigration.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\DropPreValueTable.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\DropTaskTables.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\FixLockTablePrimaryKey.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\LanguageColumns.cs" />
@@ -1242,10 +1244,6 @@
<Compile Include="PropertyEditors\ValueConverters\ColorPickerValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\DatePickerValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\DecimalValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\DropdownListMultipleValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\DropdownListMultipleWithKeysValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\DropdownListValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\DropdownListWithKeysValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\EmailAddressValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\GridValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\ImageCropperValueConverter.cs" />

View File

@@ -279,7 +279,7 @@ AnotherContentFinder
public void GetDataEditors()
{
var types = _typeLoader.GetDataEditors();
Assert.AreEqual(43, types.Count());
Assert.AreEqual(39, types.Count());
}
/// <summary>

View File

@@ -21,28 +21,15 @@ namespace Umbraco.Tests.PropertyEditors
/// Tests for the base classes of ValueEditors and PreValueEditors that are used for Property Editors that edit
/// multiple values such as the drop down list, check box list, color picker, etc....
/// </summary>
/// <remarks>
/// Mostly this used to test the we'd store INT Ids in the Db but publish STRING values or sometimes the INT values
/// to cache. Now we always just deal with strings and we'll keep the tests that show that.
/// </remarks>
[TestFixture]
public class MultiValuePropertyEditorTests
{
//TODO: Test the other formatting methods for the drop down classes
[Test]
public void DropDownMultipleValueEditor_With_Keys_Format_Data_For_Cache()
{
var dataTypeServiceMock = new Mock<IDataTypeService>();
var editor = new PublishValuesMultipleValueEditor(true, Mock.Of<ILogger>(), new DataEditorAttribute("key", "nam", "view"));
var dataType = new DataType(new CheckBoxListPropertyEditor(Mock.Of<ILogger>(), Mock.Of<ILocalizedTextService>()));
var prop = new Property(1, new PropertyType(dataType));
prop.SetValue("1234,4567,8910");
var result = editor.ConvertDbToString(prop.PropertyType, prop.GetValue(), new Mock<IDataTypeService>().Object);
Assert.AreEqual("1234,4567,8910", result);
}
[Test]
public void DropDownMultipleValueEditor_No_Keys_Format_Data_For_Cache()
public void DropDownMultipleValueEditor_Format_Data_For_Cache()
{
var dataType = new DataType(new CheckBoxListPropertyEditor(Mock.Of<ILogger>(), Mock.Of<ILocalizedTextService>()))
{
@@ -61,7 +48,7 @@ namespace Umbraco.Tests.PropertyEditors
var dataTypeService = new TestObjects.TestDataTypeService(dataType);
var prop = new Property(1, new PropertyType(dataType));
prop.SetValue("1234,4567,8910");
prop.SetValue("Value 1,Value 2,Value 3");
var valueEditor = dataType.Editor.GetValueEditor();
((DataValueEditor) valueEditor).Configuration = dataType.Configuration;
@@ -90,7 +77,7 @@ namespace Umbraco.Tests.PropertyEditors
var dataTypeService = new TestObjects.TestDataTypeService(dataType);
var prop = new Property(1, new PropertyType(dataType));
prop.SetValue("1234");
prop.SetValue("Value 2");
var result = dataType.Editor.GetValueEditor().ConvertDbToString(prop.PropertyType, prop.GetValue(), dataTypeService);

View File

@@ -1,8 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.PropertyEditors.ValueConverters;
using Umbraco.Web.PropertyEditors;
using Umbraco.Web.PropertyEditors.ValueConverters;
namespace Umbraco.Tests.PropertyEditors
{
@@ -79,27 +85,26 @@ namespace Umbraco.Tests.PropertyEditors
[TestCase(null, new string[] { })]
public void CanConvertDropdownListMultiplePropertyEditor(object value, IEnumerable<string> expected)
{
var converter = new DropdownListMultipleValueConverter();
var inter = converter.ConvertSourceToIntermediate(null, null, value, false);
var result = converter.ConvertIntermediateToObject(null, null, PropertyCacheLevel.Unknown, inter, false);
var mockPublishedContentTypeFactory = new Mock<IPublishedContentTypeFactory>();
mockPublishedContentTypeFactory.Setup(x => x.GetDataType(123))
.Returns(new PublishedDataType(123, "test", new Lazy<object>(() => new DropDownFlexibleConfiguration
{
Multiple = true
})));
var publishedPropType = new PublishedPropertyType(
new PublishedContentType(1234, "test", PublishedItemType.Content, Enumerable.Empty<string>(), Enumerable.Empty<PublishedPropertyType>(), ContentVariation.Nothing),
new PropertyType("test", ValueStorageType.Nvarchar) { DataTypeId = 123 },
new PropertyValueConverterCollection(Enumerable.Empty<IPropertyValueConverter>()),
Mock.Of<IPublishedModelFactory>(), mockPublishedContentTypeFactory.Object);
var converter = new FlexibleDropdownPropertyValueConverter();
var inter = converter.ConvertSourceToIntermediate(null, publishedPropType, value, false);
var result = converter.ConvertIntermediateToObject(null, publishedPropType, PropertyCacheLevel.Unknown, inter, false);
Assert.AreEqual(expected, result);
}
[TestCase("100", new[] { 100 })]
[TestCase("100,200", new[] { 100, 200 })]
[TestCase("100 , 200, 300 ", new[] { 100, 200, 300 })]
[TestCase("", new int[] { })]
[TestCase(null, new int[] { })]
public void CanConvertDropdownListMultipleWithKeysPropertyEditor(object value, IEnumerable<int> expected)
{
var converter = new DropdownListMultipleWithKeysValueConverter();
var inter = converter.ConvertSourceToIntermediate(null, null, value, false);
var result = converter.ConvertIntermediateToObject(null, null, PropertyCacheLevel.Unknown, inter, false);
Assert.AreEqual(expected, result);
}
[TestCase("1", 1)]
[TestCase("1", 1)]
[TestCase("0", 0)]

View File

@@ -362,12 +362,10 @@ namespace Umbraco.Tests.TestHelpers.Entities
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.NoEdit, ValueStorageType.Nvarchar) { Alias = "label", Name = "Label", Mandatory = false, SortOrder = 7, DataTypeId = -92 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.DateTime, ValueStorageType.Date) { Alias = "dateTime", Name = "Date Time", Mandatory = false, SortOrder = 8, DataTypeId = -36 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.ColorPicker, ValueStorageType.Nvarchar) { Alias = "colorPicker", Name = "Color Picker", Mandatory = false, SortOrder = 9, DataTypeId = -37 });
//that one is gone in 7.4
//contentCollection.Add(new PropertyType(Constants.PropertyEditors.FolderBrowserAlias, DataTypeDatabaseType.Nvarchar) { Alias = "folderBrowser", Name = "Folder Browser", Mandatory = false, SortOrder = 10, DataTypeDefinitionId = -38 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.DropDownListMultiple, ValueStorageType.Nvarchar) { Alias = "ddlMultiple", Name = "Dropdown List Multiple", Mandatory = false, SortOrder = 11, DataTypeId = -39 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.DropDownListFlexible, ValueStorageType.Nvarchar) { Alias = "ddlMultiple", Name = "Dropdown List Multiple", Mandatory = false, SortOrder = 11, DataTypeId = -39 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.RadioButtonList, ValueStorageType.Nvarchar) { Alias = "rbList", Name = "Radio Button List", Mandatory = false, SortOrder = 12, DataTypeId = -40 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.Date, ValueStorageType.Date) { Alias = "date", Name = "Date", Mandatory = false, SortOrder = 13, DataTypeId = -41 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.DropDownList, ValueStorageType.Integer) { Alias = "ddl", Name = "Dropdown List", Mandatory = false, SortOrder = 14, DataTypeId = -42 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.DropDownListFlexible, ValueStorageType.Integer) { Alias = "ddl", Name = "Dropdown List", Mandatory = false, SortOrder = 14, DataTypeId = -42 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.CheckBoxList, ValueStorageType.Nvarchar) { Alias = "chklist", Name = "Checkbox List", Mandatory = false, SortOrder = 15, DataTypeId = -43 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.ContentPicker, ValueStorageType.Integer) { Alias = "contentPicker", Name = "Content Picker", Mandatory = false, SortOrder = 16, DataTypeId = 1046 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.MediaPicker, ValueStorageType.Integer) { Alias = "mediaPicker", Name = "Media Picker", Mandatory = false, SortOrder = 17, DataTypeId = 1048 });
@@ -375,11 +373,6 @@ namespace Umbraco.Tests.TestHelpers.Entities
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.RelatedLinks, ValueStorageType.Ntext) { Alias = "relatedLinks", Name = "Related Links", Mandatory = false, SortOrder = 21, DataTypeId = 1050 });
contentCollection.Add(new PropertyType(Constants.PropertyEditors.Aliases.Tags, ValueStorageType.Ntext) { Alias = "tags", Name = "Tags", Mandatory = false, SortOrder = 22, DataTypeId = 1041 });
//contentCollection.Add(new PropertyType(Constants.PropertyEditors.UltraSimpleEditorAlias, DataTypeDatabaseType.Ntext) { Alias = "simpleEditor", Name = "Ultra Simple Editor", Mandatory = false, SortOrder = 19, DataTypeDefinitionId = 1038 });
//contentCollection.Add(new PropertyType(Constants.PropertyEditors.UltimatePickerAlias, DataTypeDatabaseType.Ntext) { Alias = "ultimatePicker", Name = "Ultimate Picker", Mandatory = false, SortOrder = 20, DataTypeDefinitionId = 1039 });
//contentCollection.Add(new PropertyType(Constants.PropertyEditors.MacroContainerAlias, DataTypeDatabaseType.Ntext) { Alias = "macroContainer", Name = "Macro Container", Mandatory = false, SortOrder = 23, DataTypeDefinitionId = 1042 });
//contentCollection.Add(new PropertyType(Constants.PropertyEditors.ImageCropperAlias, DataTypeDatabaseType.Ntext) { Alias = "imgCropper", Name = "Image Cropper", Mandatory = false, SortOrder = 24, DataTypeDefinitionId = 1043 });
contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 });
return contentType;

View File

@@ -1,70 +0,0 @@
angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownController",
function($scope) {
//setup the default config
var config = {
items: [],
multiple: false
};
//map the user config
angular.extend(config, $scope.model.config);
//map back to the model
$scope.model.config = config;
function convertArrayToDictionaryArray(model){
//now we need to format the items in the dictionary because we always want to have an array
var newItems = [];
for (var i = 0; i < model.length; i++) {
newItems.push({ id: model[i], sortOrder: 0, value: model[i] });
}
return newItems;
}
function convertObjectToDictionaryArray(model){
//now we need to format the items in the dictionary because we always want to have an array
var newItems = [];
var vals = _.values($scope.model.config.items);
var keys = _.keys($scope.model.config.items);
for (var i = 0; i < vals.length; i++) {
var label = vals[i].value ? vals[i].value : vals[i];
newItems.push({ id: keys[i], sortOrder: vals[i].sortOrder, value: label });
}
return newItems;
}
if (angular.isArray($scope.model.config.items)) {
//PP: I dont think this will happen, but we have tests that expect it to happen..
//if array is simple values, convert to array of objects
if(!angular.isObject($scope.model.config.items[0])){
$scope.model.config.items = convertArrayToDictionaryArray($scope.model.config.items);
}
}
else if (angular.isObject($scope.model.config.items)) {
$scope.model.config.items = convertObjectToDictionaryArray($scope.model.config.items);
}
else {
throw "The items property must be either an array or a dictionary";
}
//sort the values
$scope.model.config.items.sort(function (a, b) { return (a.sortOrder > b.sortOrder) ? 1 : ((b.sortOrder > a.sortOrder) ? -1 : 0); });
//now we need to check if the value is null/undefined, if it is we need to set it to "" so that any value that is set
// to "" gets selected by default
if ($scope.model.value === null || $scope.model.value === undefined) {
if ($scope.model.config.multiple) {
$scope.model.value = [];
}
else {
$scope.model.value = "";
}
}
});

View File

@@ -1,20 +0,0 @@
<div ng-controller="Umbraco.PropertyEditors.DropdownController" ng-switch="model.config.multiple">
<select name="dropDownList"
class="umb-property-editor umb-dropdown"
ng-switch-default
ng-model="model.value"
ng-options="item.id as item.value for item in model.config.items">
<option></option>
</select>
<!--NOTE: This ng-switch is required because ng-multiple doesn't actually support dynamic bindings with multi-select lists -->
<select name="dropDownList"
class="umb-property-editor umb-dropdown"
ng-switch-when="1"
multiple
ng-model="model.value"
ng-options="item.id as item.value for item in model.config.items">
</select>
</div>

View File

@@ -12,7 +12,10 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleCo
//map back to the model
$scope.model.config = config;
//ensure this is a bool, old data could store zeros/ones or string versions
$scope.model.config.multiple = Object.toBoolean($scope.model.config.multiple);
function convertArrayToDictionaryArray(model){
//now we need to format the items in the dictionary because we always want to have an array
var newItems = [];
@@ -74,7 +77,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleCo
// if we run in single mode we'll store the value in a local variable
// so we can pass an array as the model as our PropertyValueEditor expects that
$scope.model.singleDropdownValue = "";
if ($scope.model.config.multiple === "0") {
if (!Object.toBoolean($scope.model.config.multiple)) {
$scope.model.singleDropdownValue = Array.isArray($scope.model.value) ? $scope.model.value[0] : $scope.model.value;
}

View File

@@ -5,15 +5,15 @@
ng-switch-default
ng-change="updateSingleDropdownValue()"
ng-model="model.singleDropdownValue"
ng-options="item.id as item.value for item in model.config.items">
ng-options="item.value as item.value for item in model.config.items">
<option></option>
</select>
<!--NOTE: This ng-switch is required because ng-multiple doesn't actually support dynamic bindings with multi-select lists -->
<select name="dropDownList"
class="umb-property-editor umb-dropdown"
ng-switch-when="1"
ng-switch-when="true"
multiple
ng-model="model.value"
ng-options="item.id as item.value for item in model.config.items"></select>
ng-options="item.value as item.value for item in model.config.items"></select>
</div>

View File

@@ -31,6 +31,6 @@ namespace Umbraco.Web.PropertyEditors
protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService);
/// <inheritdoc />
protected override IDataValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(false, Attribute);
protected override IDataValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(Logger, Attribute);
}
}

View File

@@ -18,7 +18,7 @@ namespace Umbraco.Web.PropertyEditors
protected override IDataValueEditor CreateValueEditor()
{
return new PublishValuesMultipleValueEditor(false, Attribute);
return new PublishValuesMultipleValueEditor(Logger, Attribute);
}
protected override IConfigurationEditor CreateConfigurationEditor() => new DropDownFlexibleConfigurationEditor(_textService);

View File

@@ -1,73 +0,0 @@
using System.Collections.Generic;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
namespace Umbraco.Web.PropertyEditors
{
/// <summary>
/// Represents a configuration editor for the "drop down list multiple" property editor.
/// </summary>
/// <remarks>
/// <para>Ensures that 'multiple' is saved for the config in the db but is not a configuration field.</para>
/// <para>This is mostly to maintain backwards compatibility with old property editors. Devs can now simply
/// use the "drop down" property editor and check the "multiple" configuration checkbox</para>
/// <para>fixme what is multiple exactly?!</para>
/// </remarks>
internal class DropDownMultipleConfigurationEditor : ValueListConfigurationEditor
{
public DropDownMultipleConfigurationEditor(ILocalizedTextService textService)
: base(textService)
{
Fields.Add(new ConfigurationField
{
Key = "multiple",
Name = "multiple",
View = "hidden", // so it does not show in the configuration editor
HideLabel = true
});
}
// editor...
//
// receives:
// "preValues":[
// {
// "label":"Add prevalue",
// "description":"Add and remove values for the list",
// "hideLabel":false,
// "view":"multivalues",
// "config":{},
// "key":"items",
// "value":{"169":{"value":"a","sortOrder":1},"170":{"value":"b","sortOrder":2},"171":{"value":"c","sortOrder":3}}
// },
// {
// "label":"multiple",
// "description":null,
// "hideLabel":true,
// "view":"hidden",
// "config":{},
// "key":"multiple",
// "value":"1"
// }]
//
// posts ('d' being a new value):
// [{key: "items", value: [{value: "a", sortOrder: 1, id: "169"}, {value: "c", sortOrder: 3, id: "171"}, {value: "d"}]}, {key: "multiple", value: "1"}]
//
// the 'multiple' thing never goes to DB
// values go to DB with alias 0, 1, 2 + their ID + value
// the sort order that comes back makes no sense
//
// FromEditor can totally ignore 'multiple'
/// <inheritdoc/>
public override Dictionary<string, object> ToConfigurationEditor(ValueListConfiguration configuration)
{
var dictionary = base.ToConfigurationEditor(configuration);
// always add the multiple field, as 'true'
dictionary["multiple"] = 1;
return dictionary;
}
}
}

View File

@@ -1,30 +0,0 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
namespace Umbraco.Web.PropertyEditors
{
/// <summary>
/// A property editor to allow multiple selection of pre-defined items
/// </summary>
/// <remarks>
/// 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>
[DataEditor(Constants.PropertyEditors.Aliases.DropDownListMultiple, "Dropdown list multiple", "dropdown", Group = "lists", Icon="icon-bulleted-list", IsDeprecated = true)]
public class DropDownMultiplePropertyEditor : DropDownMultipleWithKeysPropertyEditor
{
/// <summary>
/// The constructor will setup the property editor based on the attribute if one is found
/// </summary>
public DropDownMultiplePropertyEditor(ILogger logger, ILocalizedTextService textService)
: base(logger, textService)
{ }
/// <inheritdoc />
protected override IDataValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(false, Attribute);
}
}

View File

@@ -1,37 +0,0 @@
using System.Collections.Generic;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
namespace Umbraco.Web.PropertyEditors
{
/// <summary>
/// Represents a property editor that allows multiple selection of pre-defined items.
/// </summary>
/// <remarks>
/// Due to backwards compatibility, this editor stores the value as a CSV string listing
/// the ids of individual items.
/// </remarks>
[DataEditor(Constants.PropertyEditors.Aliases.DropdownlistMultiplePublishKeys, "Dropdown list multiple, publish keys", "dropdown", Group = "lists", Icon = "icon-bulleted-list", IsDeprecated = true)]
public class DropDownMultipleWithKeysPropertyEditor : DropDownPropertyEditor
{
private readonly ILocalizedTextService _textService;
/// <summary>
/// Initializes a new instance of the <see cref="DropDownMultiplePropertyEditor"/> class.
/// </summary>
public DropDownMultipleWithKeysPropertyEditor(ILogger logger, ILocalizedTextService textService)
: base(logger, textService)
{
_textService = textService;
}
/// <inheritdoc />
protected override IDataValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(true, Attribute);
/// <inheritdoc />
protected override IConfigurationEditor CreateConfigurationEditor() => new DropDownMultipleConfigurationEditor(_textService);
}
}

View File

@@ -1,37 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.PropertyEditors;
using umbraco;
using ClientDependency.Core;
using Umbraco.Core.Services;
using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.PropertyEditors
{
/// <summary>
/// A property editor to allow the individual selection of pre-defined items.
/// </summary>
/// <remarks>
/// Due to remaining backwards compatible, this stores the id of the drop down item in the database which is why it is marked
/// 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>
[DataEditor(Constants.PropertyEditors.Aliases.DropDownList, "Dropdown list", "dropdown", ValueType = ValueTypes.String, Group = "lists", Icon = "icon-indent", IsDeprecated = true)]
public class DropDownPropertyEditor : DropDownWithKeysPropertyEditor
{
/// <summary>
/// The constructor will setup the property editor based on the attribute if one is found
/// </summary>
public DropDownPropertyEditor(ILogger logger, ILocalizedTextService textService)
: base(logger, textService)
{ }
/// <summary>
/// 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 IDataValueEditor CreateValueEditor() => new PublishValueValueEditor(Attribute, Logger);
}
}

View File

@@ -1,36 +0,0 @@
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
namespace Umbraco.Web.PropertyEditors
{
/// <summary>
/// A property editor to allow the individual selection of pre-defined items.
/// </summary>
/// <remarks>
/// Due to remaining backwards compatible, this stores the id of the drop down item in the database which is why it is marked
/// 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>
[DataEditor(Constants.PropertyEditors.Aliases.DropdownlistPublishKeys, "Dropdown list, publishing keys", "dropdown", ValueType = ValueTypes.Integer, Group = "lists", Icon = "icon-indent", IsDeprecated = true)]
public class DropDownWithKeysPropertyEditor : DataEditor
{
private readonly ILocalizedTextService _textService;
/// <summary>
/// The constructor will setup the property editor based on the attribute if one is found
/// </summary>
public DropDownWithKeysPropertyEditor(ILogger logger, ILocalizedTextService textService)
: base(logger)
{
_textService = textService;
}
/// <summary>
/// Return a custom pre-value editor
/// </summary>
/// <returns></returns>
protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService);
}
}

View File

@@ -1,57 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
namespace Umbraco.Web.PropertyEditors
{
/// <summary>
/// A custom value editor for any property editor that stores a pre-value int id so that we can ensure that the 'value' not the ID get's put into cache
/// </summary>
/// <remarks>
/// 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 : DataValueEditor
{
private readonly ILogger _logger;
internal PublishValueValueEditor(DataEditorAttribute attribute, ILogger logger)
: base(attribute)
{
_logger = logger;
}
/// <inheritdoc />
public override string ConvertDbToString(PropertyType propertyType, object value, IDataTypeService dataTypeService)
{
if (value == null)
return null;
// get the configuration items
// if none, fallback to base
var configuration = dataTypeService.GetDataType(propertyType.DataTypeId).ConfigurationAs<ValueListConfiguration>();
if (configuration == null)
return base.ConvertDbToString(propertyType, value, dataTypeService);
var items = configuration.Items;
var idAttempt = value.TryConvertTo<int>();
if (idAttempt.Success)
{
var itemId = idAttempt.Result;
var item = items.FirstOrDefault(x => x.Id == itemId);
if (item != null) return item.Value;
_logger.Warn<PublishValueValueEditor>("Could not find a configuration item with ID " + itemId + " for property alias " + propertyType.Alias);
}
// fallback to default
return base.ConvertDbToString(propertyType, value, dataTypeService);
}
}
}

View File

@@ -11,58 +11,19 @@ using Umbraco.Web.Composing;
namespace Umbraco.Web.PropertyEditors
{
/// <summary>
/// Custom value editor to handle posted json data and to return json data for the multiple selected items as well as ensuring
/// that the multiple selected int IDs are published to cache as a delimited string (values)
/// Custom value editor to handle posted json data and to return json data for the multiple selected items
/// </summary>
/// <remarks>
/// This is re-used by editors such as the multiple drop down list or check box list
/// </remarks>
internal class PublishValuesMultipleValueEditor : PublishValueValueEditor
internal class PublishValuesMultipleValueEditor : DataValueEditor
{
private readonly bool _publishIds;
private readonly ILogger _logger;
internal PublishValuesMultipleValueEditor(bool publishIds, ILogger logger, DataEditorAttribute attribute)
: base(attribute, logger)
internal PublishValuesMultipleValueEditor(ILogger logger, DataEditorAttribute attribute)
: base(attribute)
{
_publishIds = publishIds;
}
public PublishValuesMultipleValueEditor(bool publishIds, DataEditorAttribute attribute)
: this(publishIds, Current.Logger, attribute)
{ }
/// <summary>
/// If publishing ids, we don't need to do anything, otherwise we need to look up the pre-values and get the string values
/// </summary>
/// <param name="propertyType"></param>
/// <param name="propertyValue"></param>
/// <param name="dataTypeService"></param>
/// <returns></returns>
public override string ConvertDbToString(PropertyType propertyType, object propertyValue, IDataTypeService dataTypeService)
{
if (propertyValue == null)
return null;
//publishing ids, so just need to return the value as-is
if (_publishIds)
{
return propertyValue.ToString();
}
// get the multiple ids
// if none, fallback to base
var selectedIds = propertyValue.ToString().Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
if (selectedIds.Any() == false)
return base.ConvertDbToString(propertyType, propertyValue, dataTypeService);
// get the configuration items
// if none, fallback to base
var configuration = dataTypeService.GetDataType(propertyType.DataTypeId).ConfigurationAs<ValueListConfiguration>();
if (configuration == null)
return base.ConvertDbToString(propertyType, propertyValue, dataTypeService);
var items = configuration.Items.Where(x => selectedIds.Contains(x.Id.ToInvariantString())).Select(x => x.Value);
return string.Join(",", items);
_logger = logger;
}
/// <summary>
@@ -81,7 +42,7 @@ namespace Umbraco.Web.PropertyEditors
/// <summary>
/// When multiple values are selected a json array will be posted back so we need to format for storage in
/// the database which is a comma separated ID value
/// the database which is a comma separated string value
/// </summary>
/// <param name="editorValue"></param>
/// <param name="currentValue"></param>

View File

@@ -8,19 +8,24 @@ namespace Umbraco.Web.PropertyEditors
/// <summary>
/// A property editor to allow the individual selection of pre-defined items.
/// </summary>
/// <remarks>
/// Due to remaining backwards compatible, this stores the id of the item in the database which is why it is marked
/// 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>
[DataEditor(Constants.PropertyEditors.Aliases.RadioButtonList, "Radio button list", "radiobuttons", ValueType = ValueTypes.Integer, Group="lists", Icon="icon-target")]
public class RadioButtonsPropertyEditor : DropDownWithKeysPropertyEditor
public class RadioButtonsPropertyEditor : DataEditor
{
private readonly ILocalizedTextService _textService;
/// <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)
{ }
: base(logger)
{
_textService = textService;
}
/// <summary>
/// Return a custom pre-value editor
/// </summary>
/// <returns></returns>
protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService);
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
@@ -16,7 +17,8 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview)
{
return source?.ToString().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
return source?.ToString().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => v.Trim()).ToArray()
?? Enumerable.Empty<string>();
}
public override object ConvertIntermediateToObject(IPublishedElement owner, PublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)

View File

@@ -360,7 +360,6 @@
<Compile Include="PropertyEditors\DropDownFlexibleConfiguration.cs" />
<Compile Include="PropertyEditors\DropDownFlexiblePropertyEditor.cs" />
<Compile Include="PropertyEditors\DropDownFlexibleConfigurationEditor.cs" />
<Compile Include="PropertyEditors\DropDownMultipleConfigurationEditor.cs" />
<Compile Include="PropertyEditors\EmailAddressConfigurationEditor.cs" />
<Compile Include="PropertyEditors\EmailAddressConfiguration.cs" />
<Compile Include="PropertyEditors\GridConfiguration.cs" />
@@ -813,11 +812,9 @@
<Compile Include="PropertyEditors\DatePropertyEditor.cs" />
<Compile Include="PropertyEditors\DateTimePropertyEditor.cs" />
<Compile Include="PropertyEditors\DateTimeValidator.cs" />
<Compile Include="PropertyEditors\DropDownMultiplePropertyEditor.cs" />
<Compile Include="PropertyEditors\IntegerPropertyEditor.cs" />
<Compile Include="PropertyEditors\MultipleTextStringPropertyEditor.cs" />
<Compile Include="PropertyEditors\PublishValuesMultipleValueEditor.cs" />
<Compile Include="PropertyEditors\DropDownMultipleWithKeysPropertyEditor.cs" />
<Compile Include="PropertyEditors\RadioButtonsPropertyEditor.cs" />
<Compile Include="PropertyEditors\RichTextPreValueController.cs" />
<Compile Include="PropertyEditors\RichTextConfigurationEditor.cs" />
@@ -827,9 +824,6 @@
<Compile Include="PropertyEditors\UserPickerPropertyEditor.cs" />
<Compile Include="PropertyEditors\ValueConverters\RelatedLinksValueConverter.cs" />
<Compile Include="PropertyEditors\ValueListConfigurationEditor.cs" />
<Compile Include="PropertyEditors\DropDownPropertyEditor.cs" />
<Compile Include="PropertyEditors\PublishValueValueEditor.cs" />
<Compile Include="PropertyEditors\DropDownWithKeysPropertyEditor.cs" />
<Compile Include="PublishedContentQuery.cs" />
<Compile Include="ImageCropperTemplateExtensions.cs" />
<Compile Include="Mvc\UmbracoVirtualNodeRouteHandler.cs" />