Updates data type service for the way it saves pre-values so we can maintain ids if necessary - updates the pre-value editors to except a different dictionary which includes an id if necessary. This all fixes: U4-2751 Check that when publishing keys for drop down list prop eds that if we change a value that the id remains constistent

This commit is contained in:
Shannon
2013-10-24 16:38:00 +11:00
parent 165caa5aba
commit 36ffd41007
9 changed files with 99 additions and 58 deletions

View File

@@ -9,7 +9,11 @@
{
Value = value;
Id = id;
}
public PreValue(string value)
{
Value = value;
}
/// <summary>

View File

@@ -112,10 +112,10 @@ namespace Umbraco.Core.PropertyEditors
/// This can be overridden if perhaps you have a comma delimited string posted value but want to convert those to individual rows, or to convert
/// a json structure to multiple rows.
/// </remarks>
public virtual IDictionary<string, string> ConvertEditorToDb(IDictionary<string, object> editorValue, PreValueCollection currentValue)
public virtual IDictionary<string, PreValue> ConvertEditorToDb(IDictionary<string, object> editorValue, PreValueCollection currentValue)
{
//convert to a string based value to be saved in the db
return editorValue.ToDictionary(x => x.Key, x => x.Value == null ? null : x.Value.ToString());
return editorValue.ToDictionary(x => x.Key, x => new PreValue(x.Value == null ? null : x.Value.ToString()));
}
/// <summary>

View File

@@ -217,6 +217,7 @@ namespace Umbraco.Core.Services
/// </summary>
/// <param name="id">Id of the DataTypeDefinition to save PreValues for</param>
/// <param name="values">List of string values to save</param>
[Obsolete("This should no longer be used, use the alternative SavePreValues or SaveDataTypeAndPreValues methods instead. This will only insert pre-values without keys")]
public void SavePreValues(int id, IEnumerable<string> values)
{
//TODO: Should we raise an event here since we are really saving values for the data type?
@@ -255,9 +256,10 @@ namespace Umbraco.Core.Services
/// <param name="id"></param>
/// <param name="values"></param>
/// <remarks>
/// We will actually just remove all pre-values and re-insert them in one transaction
/// We need to actually look up each pre-value and maintain it's id if possible - this is because of silly property editors
/// like 'dropdown list publishing keys'
/// </remarks>
internal void SavePreValues(int id, IDictionary<string, string> values)
public void SavePreValues(int id, IDictionary<string, PreValue> values)
{
//TODO: Should we raise an event here since we are really saving values for the data type?
@@ -267,22 +269,7 @@ namespace Umbraco.Core.Services
{
using (var transaction = uow.Database.GetTransaction())
{
uow.Database.Execute("DELETE FROM cmsDataTypePreValues WHERE datatypeNodeId = @DataTypeId", new { DataTypeId = id });
var sortOrder = 1;
foreach (var value in values)
{
var dto = new DataTypePreValueDto
{
DataTypeNodeId = id,
Value = value.Value,
SortOrder = sortOrder,
Alias = value.Key
};
uow.Database.Insert(dto);
sortOrder++;
}
AddOrUpdatePreValues(id, values, uow);
transaction.Complete();
}
}
@@ -295,7 +282,7 @@ namespace Umbraco.Core.Services
/// <param name="dataTypeDefinition"></param>
/// <param name="values"></param>
/// <param name="userId"></param>
public void SaveDataTypeAndPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary<string, string> values, int userId = 0)
public void SaveDataTypeAndPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary<string, PreValue> values, int userId = 0)
{
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition), this))
return;
@@ -309,25 +296,7 @@ namespace Umbraco.Core.Services
repository.AddOrUpdate(dataTypeDefinition);
//complete the transaction, but run the delegate before the db transaction is finalized
uow.Commit(database =>
{
//Execute this before the transaction is completed!
database.Execute("DELETE FROM cmsDataTypePreValues WHERE datatypeNodeId = @DataTypeId", new { DataTypeId = dataTypeDefinition.Id });
var sortOrder = 1;
foreach (var value in values)
{
var dto = new DataTypePreValueDto
{
DataTypeNodeId = dataTypeDefinition.Id,
Value = value.Value,
SortOrder = sortOrder,
Alias = value.Key
};
database.Insert(dto);
sortOrder++;
}
});
uow.Commit(database => AddOrUpdatePreValues(dataTypeDefinition.Id, values, uow));
Saved.RaiseEvent(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition, false), this);
}
@@ -336,6 +305,56 @@ namespace Umbraco.Core.Services
Audit.Add(AuditTypes.Save, string.Format("Save DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id);
}
private void AddOrUpdatePreValues(int id, IDictionary<string, PreValue> preValueCollection, IDatabaseUnitOfWork uow)
{
//first just get all pre-values for this data type so we can compare them to see if we need to insert or update or replace
var sql = new Sql().Select("*")
.From<DataTypePreValueDto>()
.Where<DataTypePreValueDto>(dto => dto.DataTypeNodeId == id)
.OrderBy<DataTypePreValueDto>(dto => dto.SortOrder);
var currentVals = uow.Database.Fetch<DataTypePreValueDto>(sql).ToArray();
//already existing, need to be updated
var valueIds = preValueCollection.Where(x => x.Value.Id > 0).Select(x => x.Value.Id).ToArray();
var existingByIds = currentVals.Where(x => valueIds.Contains(x.Id)).ToArray();
//These ones need to be removed from the db, they no longer exist in the new values
var deleteById = currentVals.Where(x => valueIds.Contains(x.Id) == false);
foreach (var d in deleteById)
{
uow.Database.Execute(
"DELETE FROM cmsDataTypePreValues WHERE datatypeNodeId = @DataTypeId AND id=@Id",
new { DataTypeId = id, Id = d.Id });
}
var sortOrder = 1;
foreach (var pre in preValueCollection)
{
var existing = existingByIds.FirstOrDefault(valueDto => valueDto.Id == pre.Value.Id);
if (existing != null)
{
existing.Value = pre.Value.Value;
existing.SortOrder = sortOrder;
uow.Database.Update(existing);
}
else
{
var dto = new DataTypePreValueDto
{
DataTypeNodeId = id,
Value = pre.Value.Value,
SortOrder = sortOrder,
Alias = pre.Key
};
uow.Database.Insert(dto);
}
sortOrder++;
}
}
/// <summary>
/// Deletes an <see cref="IDataTypeDefinition"/>
/// </summary>

View File

@@ -10,8 +10,6 @@ namespace Umbraco.Core.Services
/// </summary>
public interface IDataTypeService : IService
{
void SaveDataTypeAndPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary<string, string> values, int userId = 0);
/// <summary>
/// Gets a <see cref="IDataTypeDefinition"/> by its Id
/// </summary>
@@ -107,8 +105,24 @@ namespace Umbraco.Core.Services
/// </summary>
/// <param name="id">Id of the DataTypeDefinition to save PreValues for</param>
/// <param name="values">List of string values to save</param>
[Obsolete("This should no longer be used, use the alternative SavePreValues or SaveDataTypeAndPreValues methods instead. This will only insert pre-values without keys")]
void SavePreValues(int id, IEnumerable<string> values);
/// <summary>
/// Saves a list of PreValues for a given DataTypeDefinition
/// </summary>
/// <param name="id">Id of the DataTypeDefinition to save PreValues for</param>
/// <param name="values">List of key/value pairs to save</param>
void SavePreValues(int id, IDictionary<string, PreValue> values);
/// <summary>
/// Saves the data type and it's prevalues
/// </summary>
/// <param name="dataTypeDefinition"></param>
/// <param name="values"></param>
/// <param name="userId"></param>
void SaveDataTypeAndPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary<string, PreValue> values, int userId = 0);
/// <summary>
/// Gets a specific PreValue by its Id
/// </summary>

View File

@@ -10,7 +10,10 @@ angular.module("umbraco").controller("Umbraco.Editors.MultiValuesController",
//make an array from the dictionary
var items = [];
for (var i in $scope.model.value) {
items.push({value: $scope.model.value[i]});
items.push({
value: $scope.model.value[i],
id: i
});
}
//now make the editor model the array
$scope.model.value = items;

View File

@@ -8,11 +8,6 @@ namespace Umbraco.Web.Models.ContentEditing
[DataContract(Name = "preValue", Namespace = "")]
public class PreValueFieldDisplay : PreValueFieldSave
{
///// <summary>
///// The id of the pre-value field
///// </summary>
//[DataMember(Name = "id", IsRequired = true)]
//public int Id { get; set; }
/// <summary>
/// The name to display for this pre-value field

View File

@@ -164,7 +164,7 @@ namespace Umbraco.Web.PropertyEditors
/// <param name="editorValue"></param>
/// <param name="currentValue"></param>
/// <returns></returns>
public override IDictionary<string, string> ConvertEditorToDb(IDictionary<string, object> editorValue, PreValueCollection currentValue)
public override IDictionary<string, PreValue> ConvertEditorToDb(IDictionary<string, object> editorValue, PreValueCollection currentValue)
{
var result = base.ConvertEditorToDb(editorValue, currentValue);
@@ -173,7 +173,7 @@ namespace Umbraco.Web.PropertyEditors
var values = result.Select(item => item.Value).ToList();
result.Clear();
result.Add("thumbs", string.Join(";", values));
result.Add("thumbs", new PreValue(string.Join(";", values)));
return result;
}
}

View File

@@ -56,7 +56,7 @@ namespace Umbraco.Web.PropertyEditors
/// <param name="editorValue"></param>
/// <param name="currentValue"></param>
/// <returns></returns>
public override IDictionary<string, string> ConvertEditorToDb(IDictionary<string, object> editorValue, PreValueCollection currentValue)
public override IDictionary<string, PreValue> ConvertEditorToDb(IDictionary<string, object> editorValue, PreValueCollection currentValue)
{
//the values from the editor will be min/max fieds and we need to format to json in one field
var min = (editorValue.ContainsKey("min") ? editorValue["min"].ToString() : "0").TryConvertTo<int>();
@@ -64,7 +64,7 @@ namespace Umbraco.Web.PropertyEditors
var json = JObject.FromObject(new {Minimum = min.Success ? min.Result : 0, Maximum = max.Success ? max.Result : 0});
return new Dictionary<string, string> {{"0", json.ToString(Formatting.None)}};
return new Dictionary<string, PreValue> { { "0", new PreValue(json.ToString(Formatting.None)) } };
}
/// <summary>

View File

@@ -78,10 +78,10 @@ namespace Umbraco.Web.PropertyEditors
/// <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> ConvertEditorToDb(IDictionary<string, object> editorValue, PreValueCollection currentValue)
public override IDictionary<string, PreValue> ConvertEditorToDb(IDictionary<string, object> editorValue, PreValueCollection currentValue)
{
var val = editorValue["items"] as JArray;
var result = new Dictionary<string, string>();
var result = new Dictionary<string, PreValue>();
if (val == null)
{
@@ -93,12 +93,18 @@ namespace Umbraco.Web.PropertyEditors
var index = 0;
//get all values in the array that are not empty
foreach (var asString in val.OfType<JObject>()
foreach (var item in val.OfType<JObject>()
.Where(jItem => jItem["value"] != null)
.Select(jItem => jItem["value"].ToString())
.Where(asString => asString.IsNullOrWhiteSpace() == false))
.Select(jItem => new
{
idAsString = jItem["id"] == null ? "0" : jItem["id"].ToString(),
valAsString = jItem["value"].ToString()
})
.Where(x => x.valAsString.IsNullOrWhiteSpace() == false))
{
result.Add(index.ToInvariantString(), asString);
var id = 0;
int.TryParse(item.idAsString, out id);
result.Add(index.ToInvariantString(), new PreValue(id, item.valAsString));
index++;
}
}