Updated a lot more of the pre-values stuff and the data type editor, updated lots more of the dropdown property editor and now have serialized/deserialized values working for pre-values. Now just need to finish off the pre-value field for the drop down list.

This commit is contained in:
Shannon
2013-08-22 18:38:57 +10:00
parent 6127cfccbd
commit ad4ebe3755
21 changed files with 268 additions and 109 deletions

View File

@@ -107,7 +107,7 @@ namespace Umbraco.Web.Editors
//don't persist any bound value if the editor is readonly
if (valueEditor.IsReadOnly == false)
{
dboProperty.Value = p.PropertyEditor.ValueEditor.DeserializeValue(data, dboProperty.Value);
dboProperty.Value = p.PropertyEditor.ValueEditor.FormatDataForPersistence(data, dboProperty.Value);
}
}

View File

@@ -5,6 +5,7 @@ using System.Net;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
@@ -54,8 +55,9 @@ namespace Umbraco.Web.Editors
/// Returns the pre-values for the specified property editor
/// </summary>
/// <param name="editorId"></param>
/// <param name="dataTypeId">The data type id for the pre-values, -1 if it is a new data type</param>
/// <returns></returns>
public IEnumerable<PreValueFieldDisplay> GetPreValues(Guid editorId)
public IEnumerable<PreValueFieldDisplay> GetPreValues(Guid editorId, int dataTypeId = -1)
{
var propEd = PropertyEditorResolver.Current.GetById(editorId);
if (propEd == null)
@@ -63,6 +65,29 @@ namespace Umbraco.Web.Editors
throw new InvalidOperationException("Could not find property editor with id " + editorId);
}
if (dataTypeId == -1)
{
//this is a new data type, so just return the field editors, there are no values yet
return propEd.PreValueEditor.Fields.Select(Mapper.Map<PreValueFieldDisplay>);
}
//we have a data type associated
var dataType = Services.DataTypeService.GetDataTypeDefinitionById(dataTypeId);
if (dataType == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
//now, lets check if the data type has the current editor selected, if that is true
//we will need to wire up it's saved values. Otherwise it's an existing data type
//that is changing it's underlying property editor, in which case there's no values.
if (dataType.ControlId == editorId)
{
//this is the currently assigned pre-value editor, return with values.
return Mapper.Map<IDataTypeDefinition, IEnumerable<PreValueFieldDisplay>>(dataType);
}
//return the pre value display without values
return propEd.PreValueEditor.Fields.Select(Mapper.Map<PreValueFieldDisplay>);
}
@@ -80,7 +105,23 @@ namespace Umbraco.Web.Editors
//finally we need to save the data type and it's pre-vals
var dtService = (DataTypeService) ApplicationContext.Services.DataTypeService;
var preVals = Mapper.Map<PreValueCollection>(dataType.PreValues);
//TODO: Check if the property editor has changed, if it has ensure we don't pass the
// existing values to the new property editor!
//get the prevalues, current and new
var preValDictionary = dataType.PreValues.ToDictionary(x => x.Key, x => x.Value);
var currVal = ((DataTypeService) Services.DataTypeService).GetPreValuesCollectionByDataTypeId(dataType.PersistedDataType.Id);
//we need to allow for the property editor to deserialize the prevalues
var formattedVal = dataType.PropertyEditor.PreValueEditor.FormatDataForPersistence(
preValDictionary,
currVal);
//create the pre-value collection to be saved
var preVals = new PreValueCollection(formattedVal.ToDictionary(x => x.Key, x => x.Value));
//save the data type
dtService.SaveDataTypeAndPreValues(dataType.PersistedDataType, preVals, (int)Security.CurrentUser.Id);
var display = Mapper.Map<IDataTypeDefinition, DataTypeDisplay>(dataType.PersistedDataType);

View File

@@ -42,7 +42,7 @@ namespace Umbraco.Web.Models.Mapping
var result = new T
{
Id = property.Id,
Value = editor.ValueEditor.SerializeValue(property.Value),
Value = editor.ValueEditor.FormatDataForEditor(property.Value),
Alias = property.Alias
};

View File

@@ -9,7 +9,7 @@ using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
{
/// <summary>
/// Creates a ContentPropertyDto from a Property
/// Creates a ContentPropertyDisplay from a Property
/// </summary>
internal class ContentPropertyDisplayConverter : ContentPropertyBasicConverter<ContentPropertyDisplay>
{
@@ -35,16 +35,15 @@ namespace Umbraco.Web.Models.Mapping
if (display.PropertyEditor == null)
{
display.Config = PreValueCollection.AsDictionary(preVals);
//display.Config = PreValueCollection.AsDictionary(preVals);
//if there is no property editor it means that it is a legacy data type
// we cannot support editing with that so we'll just render the readonly value view.
display.View = GlobalSettings.Path.EnsureEndsWith('/') +
"views/propertyeditors/readonlyvalue/readonlyvalue.html";
display.View = "views/propertyeditors/readonlyvalue/readonlyvalue.html";
}
else
{
//let the property editor format the pre-values
display.Config = display.PropertyEditor.FormatPreValues(display.PropertyEditor.DefaultPreValues, preVals);
display.Config = display.PropertyEditor.PreValueEditor.FormatDataForEditor(display.PropertyEditor.DefaultPreValues, preVals);
display.View = display.PropertyEditor.ValueEditor.View;
}

View File

@@ -24,6 +24,7 @@ namespace Umbraco.Web.Models.Mapping
config.CreateMap<PropertyEditor, PropertyEditorBasic>()
.ForMember(basic => basic.EditorId, expression => expression.MapFrom(editor => editor.Id));
//just maps the standard properties, does not map the value!
config.CreateMap<PreValueField, PreValueFieldDisplay>();
config.CreateMap<IDataTypeDefinition, DataTypeDisplay>()
@@ -33,15 +34,20 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(display => display.SelectedEditor, expression => expression.MapFrom(
definition => definition.ControlId == Guid.Empty ? null : (Guid?) definition.ControlId));
//gets a list of PreValueFieldDisplay objects from the data type definition
config.CreateMap<IDataTypeDefinition, IEnumerable<PreValueFieldDisplay>>()
.ConvertUsing(definition =>
{
var resolver = new PreValueDisplayResolver(lazyDataTypeService);
return resolver.Convert(definition);
});
config.CreateMap<DataTypeSave, IDataTypeDefinition>()
.ConstructUsing(save => new DataTypeDefinition(-1, save.SelectedEditor) {CreateDate = DateTime.Now})
.ForMember(definition => definition.ControlId, expression => expression.MapFrom(save => save.SelectedEditor))
.ForMember(definition => definition.ParentId, expression => expression.MapFrom(save => -1))
.ForMember(definition => definition.DatabaseType, expression => expression.ResolveUsing<DatabaseTypeResolver>());
config.CreateMap<IEnumerable<PreValueFieldSave>, PreValueCollection>()
.ConstructUsing(
saves => new PreValueCollection(saves.ToDictionary(x => x.Key, x => (object) x.Value)));
}
}
}

View File

@@ -20,7 +20,7 @@ namespace Umbraco.Web.Models.Mapping
_dataTypeService = dataTypeService;
}
protected override IEnumerable<PreValueFieldDisplay> ResolveCore(IDataTypeDefinition source)
internal IEnumerable<PreValueFieldDisplay> Convert(IDataTypeDefinition source)
{
PropertyEditor propEd = null;
if (source.ControlId != Guid.Empty)
@@ -29,20 +29,25 @@ namespace Umbraco.Web.Models.Mapping
if (propEd == null)
{
throw new InvalidOperationException("Could not find property editor with id " + source.ControlId);
}
}
}
var dataTypeService = (DataTypeService) _dataTypeService.Value;
//set up the defaults
var dataTypeService = (DataTypeService)_dataTypeService.Value;
var preVals = dataTypeService.GetPreValuesCollectionByDataTypeId(source.Id);
var dictionaryVals = PreValueCollection.AsDictionary(preVals);
IDictionary<string, object> dictionaryVals = PreValueCollection.AsDictionary(preVals).ToDictionary(x => x.Key, x => (object)x.Value);
var result = Enumerable.Empty<PreValueFieldDisplay>().ToArray();
var result = Enumerable.Empty<PreValueFieldDisplay>();
//if we have a prop editor, then format the pre-values based on it and create it's fields.
if (propEd != null)
{
result = propEd.PreValueEditor.Fields.Select(Mapper.Map<PreValueFieldDisplay>).ToArray();
result = propEd.PreValueEditor.Fields.Select(Mapper.Map<PreValueFieldDisplay>).ToArray();
dictionaryVals = propEd.PreValueEditor.FormatDataForEditor(propEd.DefaultPreValues, preVals);
}
var currentIndex = 0; //used if the collection is non-dictionary based.
//now we need to wire up the pre-values values with the actual fields defined
foreach (var field in result)
{
if (preVals.IsDictionaryBased == false)
@@ -54,7 +59,7 @@ namespace Umbraco.Web.Models.Mapping
LogHelper.Warn<PreValueDisplayResolver>("Could not find persisted pre-value for index " + currentIndex);
continue;
}
field.Value = (string) dictionaryVals.Single(x => x.Key.InvariantEquals(currentIndex.ToInvariantString())).Value;
field.Value = dictionaryVals.Single(x => x.Key.InvariantEquals(currentIndex.ToInvariantString())).Value.ToString();
currentIndex++;
}
else
@@ -65,13 +70,18 @@ namespace Umbraco.Web.Models.Mapping
LogHelper.Warn<PreValueDisplayResolver>("Could not find persisted pre-value for field " + field.Key);
continue;
}
field.Value = (string)dictionaryVals.Single(x => x.Key.InvariantEquals(field.Key)).Value;
field.Value = dictionaryVals.Single(x => x.Key.InvariantEquals(field.Key)).Value.ToString();
}
}
return result;
}
protected override IEnumerable<PreValueFieldDisplay> ResolveCore(IDataTypeDefinition source)
{
return Convert(source);
}
}
}

View File

@@ -5,36 +5,9 @@ using Newtonsoft.Json.Linq;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using umbraco;
namespace Umbraco.Web.PropertyEditors
{
[PropertyEditor(Constants.PropertyEditors.DropDownList, "Dropdown list", "dropdown")]
public class DropDownPropertyEditor : PropertyEditor
{
protected override PreValueEditor CreatePreValueEditor()
{
var editor = base.CreatePreValueEditor();
editor.Fields = new List<PreValueField>
{
new PreValueField
{
Description = "Add and remove values for the drop down list",
//we're going to call this 'temp' because we are going to override the
//serialization of the pre-values to ensure that each one gets saved with it's own key
//(new db row per pre-value, thus to maintain backwards compatibility)
Key = "temp",
Name = ui.Text("editdatatype", "addPrevalue"),
View = "Views/PropertyEditors/dropdown/dropdown.prevalue.html"
}
};
return editor;
}
}
[PropertyEditor(Constants.PropertyEditors.Date, "Date", "DATE", "datepicker")]
public class DatePropertyEditor : PropertyEditor
{
@@ -79,7 +52,7 @@ namespace Umbraco.Web.PropertyEditors
Validators = new List<ValidatorBase> { new DateTimeValidator() };
}
public override string SerializeValue(object dbValue)
public override string FormatDataForEditor(object dbValue)
{
var date = dbValue.TryConvertTo<DateTime?>();
if (date.Success == false || date.Result == null)

View File

@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.PropertyEditors
{
internal class DropDownPreValueEditor : PreValueEditor
{
/// <summary>
/// The editor is expecting a json array for a field with a key named "temp" so we need to format the persisted values
/// to this format to be used in the editor.
/// </summary>
/// <param name="defaultPreVals"></param>
/// <param name="persistedPreVals"></param>
/// <returns></returns>
public override IDictionary<string, object> FormatDataForEditor(IDictionary<string, object> defaultPreVals, PreValueCollection persistedPreVals)
{
var dictionary = PreValueCollection.AsDictionary(persistedPreVals);
var arrayOfVals = dictionary.Select(item => item.Value).ToList();
var json = JsonConvert.SerializeObject(arrayOfVals);
return new Dictionary<string, object> {{"temp", json}};
}
/// <summary>
/// Need to format the delimited posted string to individual values
/// </summary>
/// <param name="editorValue"></param>
/// <param name="currentValue"></param>
/// <returns></returns>
/// <remarks>
/// This is mostly because we want to maintain compatibility with v6 drop down property editors that store their prevalues in different db rows.
/// </remarks>
public override IDictionary<string, string> FormatDataForPersistence(IDictionary<string, string> editorValue, Core.Models.PreValueCollection currentValue)
{
var val = editorValue["temp"];
var result = new Dictionary<string, string>();
if (val.IsNullOrWhiteSpace()) return result;
try
{
var deserialized = JsonConvert.DeserializeObject<string[]>(val);
var index = 0;
foreach (var item in deserialized)
{
result.Add(index.ToInvariantString(), item);
index++;
}
}
catch (Exception ex)
{
LogHelper.Error<DropDownPreValueEditor>("Could not deserialize the posted value: " + val, ex);
}
return result;
}
}
}

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using Umbraco.Core;
using Umbraco.Core.PropertyEditors;
using umbraco;
namespace Umbraco.Web.PropertyEditors
{
[PropertyEditor(Constants.PropertyEditors.DropDownList, "Dropdown list", "dropdown")]
public class DropDownPropertyEditor : PropertyEditor
{
protected override PreValueEditor CreatePreValueEditor()
{
var editor = new DropDownPreValueEditor
{
Fields = new List<PreValueField>
{
new PreValueField
{
Description = "Add and remove values for the drop down list",
//we're going to call this 'temp' because we are going to override the
//serialization of the pre-values to ensure that each one gets saved with it's own key
//(new db row per pre-value, thus to maintain backwards compatibility)
Key = "temp",
Name = ui.Text("editdatatype", "addPrevalue"),
View = "Views/PropertyEditors/dropdown/dropdown.prevalue.html"
}
}
};
return editor;
}
}
}

View File

@@ -39,7 +39,7 @@ namespace Umbraco.Web.PropertyEditors
/// file path or use the existing file path.
/// </param>
/// <returns></returns>
public override object DeserializeValue(ContentPropertyData editorValue, object currentValue)
public override object FormatDataForPersistence(ContentPropertyData editorValue, object currentValue)
{
if (currentValue == null)
{

View File

@@ -317,6 +317,8 @@
<Compile Include="PropertyEditors\DatePropertyEditor.cs" />
<Compile Include="PropertyEditors\DateTimePropertyEditor.cs" />
<Compile Include="PropertyEditors\DateTimeValidator.cs" />
<Compile Include="PropertyEditors\DropDownPreValueEditor.cs" />
<Compile Include="PropertyEditors\DropDownPropertyEditor.cs" />
<Compile Include="PropertyEditors\LabelPropertyEditor.cs" />
<Compile Include="PropertyEditors\LabelValueEditor.cs" />
<Compile Include="Routing\UrlProviderExtensions.cs" />