Updated the data type controller post method and moved validation, etc... over to a filter, updated data type tree with the create menu action to launch into a blank element.

This commit is contained in:
Shannon
2013-08-20 17:25:17 +10:00
parent ddef2cc7ff
commit b901ae3269
12 changed files with 169 additions and 89 deletions

View File

@@ -14,7 +14,7 @@ function umbracoMenuActions($q, treeService, $location) {
/**
* @ngdoc method
* @name umbraco.services.umbracoMenuActions#RefreshNodeMenuItem
* @name umbraco.services.umbracoMenuActions#RefreshNode
* @methodOf umbraco.services.umbracoMenuActions
* @function
*
@@ -24,7 +24,7 @@ function umbracoMenuActions($q, treeService, $location) {
* @param {object} args.treeNode The tree node
* @param {object} args.section The current section
*/
"RefreshNodeMenuItem": function (args) {
"RefreshNode": function (args) {
treeService.loadNodeChildren({ node: args.treeNode, section: args.section });
},

View File

@@ -108,10 +108,7 @@ function DataTypeEditController($scope, $routeParams, $location, dataTypeResourc
contentEditingHelper.handleSaveError({
err: err,
allNewProps: $scope.preValues,
allOrigProps: $scope.preValues,
rebindCallback: function () {
createPreValueProps(err.data.preValues);
}
allOrigProps: $scope.preValues
});
});
};

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using AutoMapper;
@@ -68,79 +67,17 @@ namespace Umbraco.Web.Editors
/// </summary>
/// <param name="dataType"></param>
/// <returns></returns>
[DataTypeValidate]
public DataTypeDisplay PostSave(DataTypeSave dataType)
{
//Validate that the property editor exists
var propertyEditor = PropertyEditorResolver.Current.GetById(dataType.SelectedEditor);
if (propertyEditor == null)
{
var message = string.Format("Property editor with id: {0} was not found", dataType.SelectedEditor);
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, message));
}
//Validate the data type exists or create one if required
IDataTypeDefinition persisted;
switch (dataType.Action)
{
case ContentSaveAction.Save:
persisted = ApplicationContext.Services.DataTypeService.GetDataTypeDefinitionById(dataType.Id);
if (persisted == null)
{
var message = string.Format("Data type with id: {0} was not found", dataType.Id);
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, message));
}
//map the model to the persisted instance
Mapper.Map(dataType, persisted);
break;
case ContentSaveAction.SaveNew:
//create the persisted model from mapping the saved model
persisted = Mapper.Map<IDataTypeDefinition>(dataType);
break;
default:
throw new HttpResponseException(HttpStatusCode.NotFound);
}
//Validate each field
foreach (var preVal in dataType.PreValues)
{
var postedValue = preVal.Value;
foreach (var v in propertyEditor.PreValueEditor.Fields.SelectMany(x => x.Validators))
{
foreach (var result in v.Validate(postedValue, preVal.Key, propertyEditor))
{
//if there are no member names supplied then we assume that the validation message is for the overall property
// not a sub field on the property editor
if (!result.MemberNames.Any())
{
//add a model state error for the entire property
ModelState.AddModelError(string.Format("{0}.{1}", "Properties", preVal.Key), result.ErrorMessage);
}
else
{
//there's assigned field names so we'll combine the field name with the property name
// so that we can try to match it up to a real sub field of this editor
foreach (var field in result.MemberNames)
{
ModelState.AddModelError(string.Format("{0}.{1}.{2}", "Properties", preVal.Key, field), result.ErrorMessage);
}
}
}
}
}
if (ModelState.IsValid == false)
{
//if it is not valid, do not continue and return the model state
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Forbidden, ModelState));
}
//If we've made it here, then everything has been wired up and validated by the attribute
//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);
dtService.SaveDataTypeAndPreValues(persisted, preVals, (int)Security.CurrentUser.Id);
dtService.SaveDataTypeAndPreValues(dataType.PersistedDataType, preVals, (int)Security.CurrentUser.Id);
var display = Mapper.Map<IDataTypeDefinition, DataTypeDisplay>(persisted);
var display = Mapper.Map<IDataTypeDefinition, DataTypeDisplay>(dataType.PersistedDataType);
display.AddSuccessNotification(ui.Text("speechBubbles", "dataTypeSaved"), "");
//now return the updated model

View File

@@ -0,0 +1,119 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Editors
{
/// <summary>
/// An action filter that wires up the persisted entity of the DataTypeSave model and validates the whole request
/// </summary>
internal sealed class DataTypeValidateAttribute : ActionFilterAttribute
{
private readonly IDataTypeService _dataTypeService;
public DataTypeValidateAttribute()
{
}
public DataTypeValidateAttribute(IDataTypeService dataTypeService)
{
if (dataTypeService == null) throw new ArgumentNullException("dataTypeService");
_dataTypeService = dataTypeService;
}
private IDataTypeService DataTypeService
{
get { return _dataTypeService ?? ApplicationContext.Current.Services.DataTypeService; }
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
var dataType = (DataTypeSave)actionContext.ActionArguments["dataType"];
//Validate that the property editor exists
var propertyEditor = PropertyEditorResolver.Current.GetById(dataType.SelectedEditor);
if (propertyEditor == null)
{
var message = string.Format("Property editor with id: {0} was not found", dataType.SelectedEditor);
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
return;
}
//assign the prop editor to the model
dataType.PropertyEditor = propertyEditor;
//Validate the data type exists or create one if required
IDataTypeDefinition persisted;
switch (dataType.Action)
{
case ContentSaveAction.Save:
persisted = DataTypeService.GetDataTypeDefinitionById(dataType.Id);
if (persisted == null)
{
var message = string.Format("Data type with id: {0} was not found", dataType.Id);
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
return;
}
//map the model to the persisted instance
Mapper.Map(dataType, persisted);
break;
case ContentSaveAction.SaveNew:
//create the persisted model from mapping the saved model
persisted = Mapper.Map<IDataTypeDefinition>(dataType);
break;
default:
throw new HttpResponseException(HttpStatusCode.NotFound);
}
//now assign the persisted entity to the model so we can use it in the action
dataType.PersistedDataType = persisted;
//Validate each field
foreach (var preVal in dataType.PreValues)
{
var postedValue = preVal.Value;
foreach (var v in propertyEditor.PreValueEditor.Fields.SelectMany(x => x.Validators))
{
foreach (var result in v.Validate(postedValue, preVal.Key, propertyEditor))
{
//if there are no member names supplied then we assume that the validation message is for the overall property
// not a sub field on the property editor
if (!result.MemberNames.Any())
{
//add a model state error for the entire property
actionContext.ModelState.AddModelError(string.Format("{0}.{1}", "Properties", preVal.Key), result.ErrorMessage);
}
else
{
//there's assigned field names so we'll combine the field name with the property name
// so that we can try to match it up to a real sub field of this editor
foreach (var field in result.MemberNames)
{
actionContext.ModelState.AddModelError(string.Format("{0}.{1}.{2}", "Properties", preVal.Key, field), result.ErrorMessage);
}
}
}
}
}
if (actionContext.ModelState.IsValid == false)
{
//if it is not valid, do not continue and return the model state
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, actionContext.ModelState);
return;
}
}
}
}

View File

@@ -2,6 +2,9 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Web.Models.ContentEditing
{
@@ -25,5 +28,17 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "preValues")]
public IEnumerable<PreValueFieldSave> PreValues { get; set; }
/// <summary>
/// The real persisted data type
/// </summary>
[JsonIgnore]
internal IDataTypeDefinition PersistedDataType { get; set; }
/// <summary>
/// The PropertyEditor assigned
/// </summary>
[JsonIgnore]
internal PropertyEditor PropertyEditor { get; set; }
}
}

View File

@@ -111,7 +111,7 @@ namespace Umbraco.Web.Trees
// add default actions for *all* users
allowedMenu.AddMenuItem<ActionRePublish>();
allowedMenu.AddMenuItem<RefreshNodeMenuItem, ActionRefresh>(true);
allowedMenu.AddMenuItem<RefreshNode, ActionRefresh>(true);
return allowedMenu;
}
@@ -155,7 +155,7 @@ namespace Umbraco.Web.Trees
menu.AddMenuItem<ActionNotify>(true);
menu.AddMenuItem<ActionSendToTranslate>();
menu.AddMenuItem<RefreshNodeMenuItem, ActionRefresh>(true);
menu.AddMenuItem<RefreshNode, ActionRefresh>(true);
return menu;
}

View File

@@ -45,8 +45,8 @@ namespace Umbraco.Web.Trees
if (id == Constants.System.Root.ToInvariantString())
{
// root actions
menu.AddMenuItem<ActionNew>();
menu.AddMenuItem<RefreshNodeMenuItem, ActionRefresh>(true);
menu.AddMenuItem<CreateChildEntity, ActionNew>();
menu.AddMenuItem<RefreshNode, ActionRefresh>(true);
return menu;
}

View File

@@ -47,7 +47,7 @@ namespace Umbraco.Web.Trees
// root actions
menu.AddMenuItem<ActionNew>();
menu.AddMenuItem<ActionSort>(true);
menu.AddMenuItem<RefreshNodeMenuItem, ActionRefresh>(true);
menu.AddMenuItem<RefreshNode, ActionRefresh>(true);
return menu;
}

View File

@@ -0,0 +1,10 @@
namespace Umbraco.Web.Trees.Menu
{
/// <summary>
/// Represents the refresh node menu item
/// </summary>
[ActionMenuItem("umbracoMenuActions")]
public sealed class CreateChildEntity : ActionMenuItem
{
}
}

View File

@@ -1,10 +1,10 @@
namespace Umbraco.Web.Trees.Menu
{
/// <summary>
/// Represents the refresh node menu item
/// </summary>
[ActionMenuItem("umbracoMenuActions")]
public sealed class RefreshNodeMenuItem : ActionMenuItem
{
}
namespace Umbraco.Web.Trees.Menu
{
/// <summary>
/// Represents the refresh node menu item
/// </summary>
[ActionMenuItem("umbracoMenuActions")]
public sealed class RefreshNode : ActionMenuItem
{
}
}

View File

@@ -299,6 +299,7 @@
<Compile Include="Editors\AuthenticationController.cs" />
<Compile Include="Editors\ContentController.cs" />
<Compile Include="Editors\DataTypeController.cs" />
<Compile Include="Editors\DataTypeValidateAttribute.cs" />
<Compile Include="Editors\EntityController.cs" />
<Compile Include="Models\ContentEditing\DataTypeDisplay.cs" />
<Compile Include="Models\ContentEditing\DataTypeSave.cs" />
@@ -320,6 +321,7 @@
<Compile Include="PropertyEditors\LabelValueEditor.cs" />
<Compile Include="Routing\UrlProviderExtensions.cs" />
<Compile Include="Trees\DataTypeTreeController.cs" />
<Compile Include="Trees\Menu\CreateChildEntity.cs" />
<Compile Include="WebApi\ControllerContextExtensions.cs" />
<Compile Include="WebApi\CustomDateTimeConvertor.cs" />
<Compile Include="Models\ContentEditing\ContentSortOrder.cs" />
@@ -379,7 +381,7 @@
<Compile Include="Trees\Menu\MenuItem.cs" />
<Compile Include="Trees\Menu\MenuItemCollection.cs" />
<Compile Include="Trees\Menu\MenuItemExtensions.cs" />
<Compile Include="Trees\Menu\RefreshNodeMenuItem.cs" />
<Compile Include="Trees\Menu\RefreshNode.cs" />
<Compile Include="Trees\SearchResultItem.cs" />
<Compile Include="Trees\SectionRootNode.cs" />
<Compile Include="Trees\TreeApiController.cs" />

View File

@@ -9,7 +9,7 @@ namespace umbraco.BusinessLogic.Actions
/// Concerns only the tree itself and thus you should not handle
/// this action from without umbraco.
/// </summary>
[LegacyActionMenuItem("umbracoMenuActions", "RefreshNodeMenuItem")]
[LegacyActionMenuItem("umbracoMenuActions", "RefreshNode")]
public class ActionRefresh : IAction
{
//create singleton