Wires up the correct saving logic for media types + validation, refactors the logic so it can be reused everywhere.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* @name umbraco.resources.mediaTypeResource
|
||||
* @description Loads in data for media types
|
||||
**/
|
||||
function mediaTypeResource($q, $http, umbRequestHelper) {
|
||||
function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
|
||||
return {
|
||||
|
||||
@@ -81,12 +81,10 @@ function mediaTypeResource($q, $http, umbRequestHelper) {
|
||||
|
||||
save: function (contentType) {
|
||||
|
||||
var saveModel = umbDataFormatter.formatContentTypePostData(contentType);
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"PostSave"
|
||||
), contentType),
|
||||
$http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl", "PostSave"), saveModel),
|
||||
'Failed to save data for content type id ' + contentType.id);
|
||||
},
|
||||
|
||||
|
||||
@@ -154,33 +154,12 @@
|
||||
vm.contentType = contentTypeHelper.updateTemplatePlaceholder(vm.contentType);
|
||||
}
|
||||
|
||||
//contentTypeResource.save(vm.contentType).then(function(dt){
|
||||
|
||||
// formHelper.resetForm({ scope: $scope, notifications: dt.notifications });
|
||||
// contentEditingHelper.handleSuccessfulSave({
|
||||
// scope: $scope,
|
||||
// savedContent: dt,
|
||||
// rebindCallback: function() {
|
||||
|
||||
// }
|
||||
// });
|
||||
|
||||
// notificationsService.success("Document type save");
|
||||
// //post save logic here -the saved doctype returns as a new object
|
||||
// init(dt);
|
||||
|
||||
// syncTreeNode(vm.contentType, dt.path);
|
||||
|
||||
// vm.page.saveButtonState = "success";
|
||||
|
||||
//});
|
||||
|
||||
contentEditingHelper.contentEditorPerformSave({
|
||||
statusMessage: "Saving...",
|
||||
saveMethod: contentTypeResource.save,
|
||||
scope: $scope,
|
||||
content: vm.contentType,
|
||||
//no-op for rebind callback... we don't really need to rebind for content types
|
||||
//no-op for rebind callback... we don't really need to rebind for content types
|
||||
rebindCallback: angular.noop
|
||||
}).then(function (data) {
|
||||
//success
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
function MediaTypesEditController($scope, $routeParams, mediaTypeResource, dataTypeResource, editorState, contentEditingHelper, formHelper, navigationService, iconHelper, contentTypeHelper, notificationsService, $filter) {
|
||||
function MediaTypesEditController($scope, $routeParams, mediaTypeResource, dataTypeResource, editorState, contentEditingHelper, formHelper, navigationService, iconHelper, contentTypeHelper, notificationsService, $filter, $q) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
@@ -125,49 +125,47 @@
|
||||
|
||||
function save() {
|
||||
|
||||
// validate form
|
||||
if (formHelper.submitForm({ scope: $scope })) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
formHelper.resetForm({ scope: $scope });
|
||||
vm.page.saveButtonState = "busy";
|
||||
|
||||
// if form validates - perform save
|
||||
performSave();
|
||||
// reformat allowed content types to array if id's
|
||||
vm.contentType.allowedContentTypes = contentTypeHelper.createIdArray(vm.contentType.allowedContentTypes);
|
||||
|
||||
}
|
||||
// update placeholder template information on new doc types
|
||||
if (!$routeParams.notemplate && vm.contentType.id === 0) {
|
||||
vm.contentType = contentTypeHelper.updateTemplatePlaceholder(vm.contentType);
|
||||
}
|
||||
|
||||
contentEditingHelper.contentEditorPerformSave({
|
||||
statusMessage: "Saving...",
|
||||
saveMethod: mediaTypeResource.save,
|
||||
scope: $scope,
|
||||
content: vm.contentType,
|
||||
//no-op for rebind callback... we don't really need to rebind for content types
|
||||
rebindCallback: angular.noop
|
||||
}).then(function (data) {
|
||||
//success
|
||||
syncTreeNode(vm.contentType, data.path);
|
||||
|
||||
vm.page.saveButtonState = "success";
|
||||
|
||||
deferred.resolve(data);
|
||||
}, function (err) {
|
||||
//error
|
||||
if (err) {
|
||||
editorState.set($scope.content);
|
||||
}
|
||||
|
||||
vm.page.saveButtonState = "error";
|
||||
|
||||
deferred.reject(err);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
|
||||
}
|
||||
|
||||
function performSave() {
|
||||
|
||||
vm.page.saveButtonState = "busy";
|
||||
|
||||
// reformat allowed content types to array if id's
|
||||
vm.contentType.allowedContentTypes = contentTypeHelper.createIdArray(vm.contentType.allowedContentTypes);
|
||||
|
||||
mediaTypeResource.save(vm.contentType).then(function(dt){
|
||||
|
||||
formHelper.resetForm({ scope: $scope, notifications: dt.notifications });
|
||||
contentEditingHelper.handleSuccessfulSave({
|
||||
scope: $scope,
|
||||
savedContent: dt,
|
||||
rebindCallback: function() {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
notificationsService.success("Media type saved");
|
||||
//post save logic here -the saved doctype returns as a new object
|
||||
init(dt);
|
||||
|
||||
syncTreeNode(vm.contentType, dt.path);
|
||||
|
||||
vm.page.saveButtonState = "success";
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
function init(contentType){
|
||||
|
||||
// set all tab to inactive
|
||||
|
||||
@@ -90,134 +90,33 @@ namespace Umbraco.Web.Editors
|
||||
: Request.CreateValidationErrorResponse(result.Exception.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the composition and adds errors to the model state if any are found then throws an error response if there are errors
|
||||
/// </summary>
|
||||
/// <param name="contentTypeSave"></param>
|
||||
/// <param name="composition"></param>
|
||||
/// <returns></returns>
|
||||
private void ValidateComposition(ContentTypeSave contentTypeSave, IContentTypeComposition composition)
|
||||
{
|
||||
var validateAttempt = Services.ContentTypeService.ValidateComposition(composition);
|
||||
if (validateAttempt == false)
|
||||
{
|
||||
//if it's not successful then we need to return some model state for the property aliases that
|
||||
// are duplicated
|
||||
var propertyAliases = validateAttempt.Result.Distinct();
|
||||
foreach (var propertyAlias in propertyAliases)
|
||||
{
|
||||
//find the property relating to these
|
||||
var prop = contentTypeSave.Groups.SelectMany(x => x.Properties).Single(x => x.Alias == propertyAlias);
|
||||
var group = contentTypeSave.Groups.Single(x => x.Properties.Contains(prop));
|
||||
var propIndex = group.Properties.IndexOf(prop);
|
||||
var groupIndex = contentTypeSave.Groups.IndexOf(group);
|
||||
|
||||
var key = string.Format("Groups[{0}].Properties[{1}].Alias", groupIndex, propIndex);
|
||||
ModelState.AddModelError(key, "Duplicate property aliases not allowed between compositions");
|
||||
}
|
||||
|
||||
var display = Mapper.Map<ContentTypeDisplay>(composition);
|
||||
//map the 'save' data on top
|
||||
display = Mapper.Map(contentTypeSave, display);
|
||||
display.Errors = ModelState.ToErrorDictionary();
|
||||
throw new HttpResponseException(Request.CreateValidationErrorResponse(display));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public ContentTypeDisplay PostSave(ContentTypeSave contentTypeSave)
|
||||
{
|
||||
var ctId = Convert.ToInt32(contentTypeSave.Id);
|
||||
|
||||
var ctService = Services.ContentTypeService;
|
||||
|
||||
if (ModelState.IsValid == false)
|
||||
{
|
||||
var ct = ctService.GetContentType(ctId);
|
||||
//Required data is invalid so we cannot continue
|
||||
var forDisplay = Mapper.Map<ContentTypeDisplay>(ct);
|
||||
//map the 'save' data on top
|
||||
forDisplay = Mapper.Map(contentTypeSave, forDisplay);
|
||||
forDisplay.Errors = ModelState.ToErrorDictionary();
|
||||
throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay));
|
||||
}
|
||||
|
||||
//filter out empty properties
|
||||
contentTypeSave.Groups = contentTypeSave.Groups.Where(x => x.Name.IsNullOrWhiteSpace() == false).ToList();
|
||||
foreach (var group in contentTypeSave.Groups)
|
||||
{
|
||||
group.Properties = group.Properties.Where(x => x.Alias.IsNullOrWhiteSpace() == false).ToList();
|
||||
}
|
||||
|
||||
//TODO: This all needs to be done in a transaction!!
|
||||
// Which means that all of this logic needs to take place inside the service
|
||||
|
||||
ContentTypeDisplay display;
|
||||
|
||||
if (ctId > 0)
|
||||
{
|
||||
//its an update to an existing
|
||||
var found = ctService.GetContentType(ctId);
|
||||
if (found == null)
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
|
||||
Mapper.Map(contentTypeSave, found);
|
||||
|
||||
//NOTE: this throws an error response if it is not valid
|
||||
ValidateComposition(contentTypeSave, found);
|
||||
|
||||
ctService.Save(found);
|
||||
display = Mapper.Map<ContentTypeDisplay>(found);
|
||||
}
|
||||
else
|
||||
{
|
||||
//set id to null to ensure its handled as a new type
|
||||
contentTypeSave.Id = null;
|
||||
contentTypeSave.CreateDate = DateTime.Now;
|
||||
contentTypeSave.UpdateDate = DateTime.Now;
|
||||
|
||||
//create a default template if it doesnt exist -but only if default template is == to the content type
|
||||
//TODO: Is this really what we want? What if we don't want any template assigned at all ?
|
||||
if (contentTypeSave.DefaultTemplate.IsNullOrWhiteSpace() == false && contentTypeSave.DefaultTemplate == contentTypeSave.Alias)
|
||||
var savedCt = PerformPostSave(
|
||||
contentTypeSave: contentTypeSave,
|
||||
getContentType: i => Services.ContentTypeService.GetContentType(i),
|
||||
saveContentType: type => Services.ContentTypeService.Save(type),
|
||||
beforeCreateNew: ctSave =>
|
||||
{
|
||||
var template = Services.FileService.GetTemplate(contentTypeSave.Alias);
|
||||
if (template == null)
|
||||
//create a default template if it doesnt exist -but only if default template is == to the content type
|
||||
//TODO: Is this really what we want? What if we don't want any template assigned at all ?
|
||||
if (ctSave.DefaultTemplate.IsNullOrWhiteSpace() == false && ctSave.DefaultTemplate == ctSave.Alias)
|
||||
{
|
||||
template = new Template(contentTypeSave.Name, contentTypeSave.Alias);
|
||||
Services.FileService.SaveTemplate(template);
|
||||
var template = Services.FileService.GetTemplate(ctSave.Alias);
|
||||
if (template == null)
|
||||
{
|
||||
template = new Template(ctSave.Name, ctSave.Alias);
|
||||
Services.FileService.SaveTemplate(template);
|
||||
}
|
||||
|
||||
//make sure the template alias is set on the default and allowed template so we can map it back
|
||||
ctSave.DefaultTemplate = template.Alias;
|
||||
}
|
||||
});
|
||||
|
||||
//make sure the template alias is set on the default and allowed template so we can map it back
|
||||
contentTypeSave.DefaultTemplate = template.Alias;
|
||||
}
|
||||
|
||||
//check if the type is trying to allow type 0 below itself - id zero refers to the currently unsaved type
|
||||
//always filter these 0 types out
|
||||
var allowItselfAsChild = false;
|
||||
if (contentTypeSave.AllowedContentTypes != null)
|
||||
{
|
||||
allowItselfAsChild = contentTypeSave.AllowedContentTypes.Any(x => x == 0);
|
||||
contentTypeSave.AllowedContentTypes = contentTypeSave.AllowedContentTypes.Where(x => x > 0).ToList();
|
||||
}
|
||||
|
||||
//save as new
|
||||
var newCt = Mapper.Map<IContentType>(contentTypeSave);
|
||||
|
||||
//NOTE: this throws an error response if it is not valid
|
||||
ValidateComposition(contentTypeSave, newCt);
|
||||
|
||||
ctService.Save(newCt);
|
||||
|
||||
//we need to save it twice to allow itself under itself.
|
||||
if (allowItselfAsChild)
|
||||
{
|
||||
//NOTE: This will throw if the composition isn't right... but it shouldn't be at this stage
|
||||
newCt.AddContentType(newCt);
|
||||
ctService.Save(newCt);
|
||||
}
|
||||
|
||||
display = Mapper.Map<ContentTypeDisplay>(newCt);
|
||||
}
|
||||
var display = Mapper.Map<ContentTypeDisplay>(savedCt);
|
||||
|
||||
display.AddSuccessNotification(
|
||||
Services.TextService.Localize("speechBubbles/contentTypeSavedHeader"),
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
}
|
||||
|
||||
public DataTypeBasic GetAssignedListViewDataType(int contentTypeId)
|
||||
protected internal DataTypeBasic GetAssignedListViewDataType(int contentTypeId)
|
||||
{
|
||||
var objectType = Services.EntityService.GetObjectType(contentTypeId);
|
||||
|
||||
@@ -81,12 +81,12 @@ namespace Umbraco.Web.Editors
|
||||
/// Gets all user defined properties.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<string> GetAllPropertyTypeAliases()
|
||||
protected IEnumerable<string> GetAllPropertyTypeAliases()
|
||||
{
|
||||
return ApplicationContext.Services.ContentTypeService.GetAllPropertyTypeAliases();
|
||||
}
|
||||
|
||||
public ContentPropertyDisplay GetPropertyTypeScaffold(int id)
|
||||
protected ContentPropertyDisplay GetPropertyTypeScaffold(int id)
|
||||
{
|
||||
var dataTypeDiff = Services.DataTypeService.GetDataTypeDefinitionById(id);
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace Umbraco.Web.Editors
|
||||
};
|
||||
}
|
||||
|
||||
public dynamic GetSafeAlias(string value, bool camelCase = true)
|
||||
protected dynamic GetSafeAlias(string value, bool camelCase = true)
|
||||
{
|
||||
var returnValue = (string.IsNullOrWhiteSpace(value)) ? string.Empty : value.ToSafeAlias(camelCase);
|
||||
dynamic returnObj = new System.Dynamic.ExpandoObject();
|
||||
@@ -118,9 +118,42 @@ namespace Umbraco.Web.Editors
|
||||
return returnObj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the composition and adds errors to the model state if any are found then throws an error response if there are errors
|
||||
/// </summary>
|
||||
/// <param name="contentTypeSave"></param>
|
||||
/// <param name="composition"></param>
|
||||
/// <returns></returns>
|
||||
protected void ValidateComposition(ContentTypeSave contentTypeSave, IContentTypeComposition composition)
|
||||
{
|
||||
var validateAttempt = Services.ContentTypeService.ValidateComposition(composition);
|
||||
if (validateAttempt == false)
|
||||
{
|
||||
//if it's not successful then we need to return some model state for the property aliases that
|
||||
// are duplicated
|
||||
var propertyAliases = validateAttempt.Result.Distinct();
|
||||
foreach (var propertyAlias in propertyAliases)
|
||||
{
|
||||
//find the property relating to these
|
||||
var prop = contentTypeSave.Groups.SelectMany(x => x.Properties).Single(x => x.Alias == propertyAlias);
|
||||
var group = contentTypeSave.Groups.Single(x => x.Properties.Contains(prop));
|
||||
var propIndex = group.Properties.IndexOf(prop);
|
||||
var groupIndex = contentTypeSave.Groups.IndexOf(group);
|
||||
|
||||
var key = string.Format("Groups[{0}].Properties[{1}].Alias", groupIndex, propIndex);
|
||||
ModelState.AddModelError(key, "Duplicate property aliases not allowed between compositions");
|
||||
}
|
||||
|
||||
public string TranslateItem(string text)
|
||||
var display = Mapper.Map<ContentTypeDisplay>(composition);
|
||||
//map the 'save' data on top
|
||||
display = Mapper.Map(contentTypeSave, display);
|
||||
display.Errors = ModelState.ToErrorDictionary();
|
||||
throw new HttpResponseException(Request.CreateValidationErrorResponse(display));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected string TranslateItem(string text)
|
||||
{
|
||||
if (text == null)
|
||||
{
|
||||
@@ -134,6 +167,89 @@ namespace Umbraco.Web.Editors
|
||||
return CultureDictionary[text].IfNullOrWhiteSpace(text);
|
||||
}
|
||||
|
||||
protected TContentType PerformPostSave<TContentType>(
|
||||
ContentTypeSave contentTypeSave,
|
||||
Func<int, TContentType> getContentType,
|
||||
Action<TContentType> saveContentType,
|
||||
Action<ContentTypeSave> beforeCreateNew = null)
|
||||
where TContentType : IContentTypeComposition
|
||||
{
|
||||
var ctId = Convert.ToInt32(contentTypeSave.Id);
|
||||
|
||||
if (ModelState.IsValid == false)
|
||||
{
|
||||
var ct = getContentType(ctId);
|
||||
//Required data is invalid so we cannot continue
|
||||
var forDisplay = Mapper.Map<ContentTypeCompositionDisplay>(ct);
|
||||
//map the 'save' data on top
|
||||
forDisplay = Mapper.Map(contentTypeSave, forDisplay);
|
||||
forDisplay.Errors = ModelState.ToErrorDictionary();
|
||||
throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay));
|
||||
}
|
||||
|
||||
//filter out empty properties
|
||||
contentTypeSave.Groups = contentTypeSave.Groups.Where(x => x.Name.IsNullOrWhiteSpace() == false).ToList();
|
||||
foreach (var group in contentTypeSave.Groups)
|
||||
{
|
||||
group.Properties = group.Properties.Where(x => x.Alias.IsNullOrWhiteSpace() == false).ToList();
|
||||
}
|
||||
|
||||
if (ctId > 0)
|
||||
{
|
||||
//its an update to an existing
|
||||
var found = getContentType(ctId);
|
||||
if (found == null)
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
|
||||
Mapper.Map(contentTypeSave, found);
|
||||
|
||||
//NOTE: this throws an error response if it is not valid
|
||||
ValidateComposition(contentTypeSave, found);
|
||||
|
||||
saveContentType(found);
|
||||
|
||||
return found;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (beforeCreateNew != null)
|
||||
{
|
||||
beforeCreateNew(contentTypeSave);
|
||||
}
|
||||
|
||||
//set id to null to ensure its handled as a new type
|
||||
contentTypeSave.Id = null;
|
||||
contentTypeSave.CreateDate = DateTime.Now;
|
||||
contentTypeSave.UpdateDate = DateTime.Now;
|
||||
|
||||
//check if the type is trying to allow type 0 below itself - id zero refers to the currently unsaved type
|
||||
//always filter these 0 types out
|
||||
var allowItselfAsChild = false;
|
||||
if (contentTypeSave.AllowedContentTypes != null)
|
||||
{
|
||||
allowItselfAsChild = contentTypeSave.AllowedContentTypes.Any(x => x == 0);
|
||||
contentTypeSave.AllowedContentTypes = contentTypeSave.AllowedContentTypes.Where(x => x > 0).ToList();
|
||||
}
|
||||
|
||||
//save as new
|
||||
var newCt = Mapper.Map<TContentType>(contentTypeSave);
|
||||
|
||||
//NOTE: this throws an error response if it is not valid
|
||||
ValidateComposition(contentTypeSave, newCt);
|
||||
|
||||
saveContentType(newCt);
|
||||
|
||||
//we need to save it twice to allow itself under itself.
|
||||
if (allowItselfAsChild)
|
||||
{
|
||||
//NOTE: This will throw if the composition isn't right... but it shouldn't be at this stage
|
||||
newCt.AddContentType(newCt);
|
||||
saveContentType(newCt);
|
||||
}
|
||||
return newCt;
|
||||
}
|
||||
}
|
||||
|
||||
private ICultureDictionary CultureDictionary
|
||||
{
|
||||
get
|
||||
|
||||
@@ -14,7 +14,9 @@ using System.Net;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using Umbraco.Web.WebApi;
|
||||
using ContentType = System.Net.Mime.ContentType;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
@@ -100,58 +102,20 @@ namespace Umbraco.Web.Editors
|
||||
.Select(Mapper.Map<IMediaType, ContentTypeBasic>);
|
||||
}
|
||||
|
||||
public ContentTypeCompositionDisplay PostSave(ContentTypeCompositionDisplay contentType)
|
||||
public ContentTypeCompositionDisplay PostSave(ContentTypeSave contentTypeSave)
|
||||
{
|
||||
var savedCt = PerformPostSave(
|
||||
contentTypeSave: contentTypeSave,
|
||||
getContentType: i => Services.ContentTypeService.GetMediaType(i),
|
||||
saveContentType: type => Services.ContentTypeService.Save(type));
|
||||
|
||||
var ctService = ApplicationContext.Services.ContentTypeService;
|
||||
var display = Mapper.Map<ContentTypeCompositionDisplay>(savedCt);
|
||||
|
||||
//TODO: warn on content type alias conflicts
|
||||
//TODO: warn on property alias conflicts
|
||||
|
||||
//TODO: Validate the submitted model
|
||||
|
||||
//filter out empty properties
|
||||
contentType.Groups = contentType.Groups.Where(x => x.Name.IsNullOrWhiteSpace() == false).ToList();
|
||||
foreach (var group in contentType.Groups)
|
||||
{
|
||||
group.Properties = group.Properties.Where(x => x.Alias.IsNullOrWhiteSpace() == false).ToList();
|
||||
}
|
||||
|
||||
var ctId = Convert.ToInt32(contentType.Id);
|
||||
|
||||
if (ctId > 0)
|
||||
{
|
||||
//its an update to an existing
|
||||
IMediaType found = ctService.GetMediaType(ctId);
|
||||
if (found == null)
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
|
||||
Mapper.Map(contentType, found);
|
||||
ctService.Save(found);
|
||||
|
||||
//map the saved item back to the content type (it should now get id etc set)
|
||||
Mapper.Map(found, contentType);
|
||||
return contentType;
|
||||
}
|
||||
else
|
||||
{
|
||||
//ensure alias is set
|
||||
if (string.IsNullOrEmpty(contentType.Alias))
|
||||
contentType.Alias = contentType.Name.ToSafeAlias();
|
||||
|
||||
contentType.Id = null;
|
||||
|
||||
//save as new
|
||||
IMediaType newCt = new MediaType(-1);
|
||||
Mapper.Map(contentType, newCt);
|
||||
|
||||
ctService.Save(newCt);
|
||||
|
||||
//map the saved item back to the content type (it should now get id etc set)
|
||||
Mapper.Map(newCt, contentType);
|
||||
return contentType;
|
||||
}
|
||||
display.AddSuccessNotification(
|
||||
Services.TextService.Localize("speechBubbles/contentTypeSavedHeader"),
|
||||
string.Empty);
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Web.Security;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Mvc;
|
||||
@@ -105,58 +106,20 @@ namespace Umbraco.Web.Editors
|
||||
return Enumerable.Empty<ContentTypeBasic>();
|
||||
}
|
||||
|
||||
public ContentTypeCompositionDisplay PostSave(ContentTypeCompositionDisplay contentType)
|
||||
public ContentTypeCompositionDisplay PostSave(ContentTypeSave contentTypeSave)
|
||||
{
|
||||
var savedCt = PerformPostSave(
|
||||
contentTypeSave: contentTypeSave,
|
||||
getContentType: i => Services.MemberTypeService.Get(i),
|
||||
saveContentType: type => Services.MemberTypeService.Save(type));
|
||||
|
||||
var ctService = ApplicationContext.Services.MemberTypeService;
|
||||
var display = Mapper.Map<ContentTypeCompositionDisplay>(savedCt);
|
||||
|
||||
//TODO: warn on content type alias conflicts
|
||||
//TODO: warn on property alias conflicts
|
||||
|
||||
//TODO: Validate the submitted model
|
||||
|
||||
//filter out empty properties
|
||||
contentType.Groups = contentType.Groups.Where(x => x.Name.IsNullOrWhiteSpace() == false).ToList();
|
||||
foreach (var group in contentType.Groups)
|
||||
{
|
||||
group.Properties = group.Properties.Where(x => x.Alias.IsNullOrWhiteSpace() == false).ToList();
|
||||
}
|
||||
|
||||
var ctId = Convert.ToInt32(contentType.Id);
|
||||
|
||||
if (ctId > 0)
|
||||
{
|
||||
//its an update to an existing
|
||||
IMemberType found = ctService.Get(ctId);
|
||||
if (found == null)
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
|
||||
Mapper.Map(contentType, found);
|
||||
ctService.Save(found);
|
||||
|
||||
//map the saved item back to the content type (it should now get id etc set)
|
||||
Mapper.Map(found, contentType);
|
||||
return contentType;
|
||||
}
|
||||
else
|
||||
{
|
||||
//ensure alias is set
|
||||
if (string.IsNullOrEmpty(contentType.Alias))
|
||||
contentType.Alias = contentType.Name.ToSafeAlias();
|
||||
|
||||
contentType.Id = null;
|
||||
|
||||
//save as new
|
||||
IMemberType newCt = new MemberType(-1);
|
||||
Mapper.Map(contentType, newCt);
|
||||
|
||||
ctService.Save(newCt);
|
||||
|
||||
//map the saved item back to the content type (it should now get id etc set)
|
||||
Mapper.Map(newCt, contentType);
|
||||
return contentType;
|
||||
}
|
||||
display.AddSuccessNotification(
|
||||
Services.TextService.Localize("speechBubbles/contentTypeSavedHeader"),
|
||||
string.Empty);
|
||||
|
||||
return display;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,6 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(type => type.UpdateDate, expression => expression.Ignore())
|
||||
.ForMember(type => type.HasIdentity, expression => expression.Ignore());
|
||||
|
||||
|
||||
config.CreateMap<ContentTypeSave, IContentType>()
|
||||
//do the base mapping
|
||||
.MapBaseContentTypeSaveToEntity(applicationContext)
|
||||
@@ -64,84 +63,29 @@ namespace Umbraco.Web.Models.Mapping
|
||||
if (source.DefaultTemplate != null)
|
||||
dest.SetDefaultTemplate(applicationContext.Services.FileService.GetTemplate(source.DefaultTemplate));
|
||||
|
||||
//sync compositions
|
||||
var current = dest.CompositionAliases().ToArray();
|
||||
var proposed = source.CompositeContentTypes;
|
||||
|
||||
var remove = current.Where(x => proposed.Contains(x) == false);
|
||||
var add = proposed.Where(x => current.Contains(x) == false);
|
||||
|
||||
foreach (var rem in remove)
|
||||
{
|
||||
dest.RemoveContentType(rem);
|
||||
}
|
||||
|
||||
foreach (var a in add)
|
||||
{
|
||||
|
||||
//TODO: Remove N+1 lookup
|
||||
var addCt = applicationContext.Services.ContentTypeService.GetContentType(a);
|
||||
if (addCt != null)
|
||||
dest.AddContentType(addCt);
|
||||
}
|
||||
ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext);
|
||||
});
|
||||
|
||||
|
||||
|
||||
//config.CreateMap<ContentTypeCompositionDisplay, IMemberType>()
|
||||
// //do the base mapping
|
||||
// .MapBaseContentTypeSaveToEntity(applicationContext)
|
||||
// .AfterMap((source, dest) =>
|
||||
// {
|
||||
|
||||
// //sync compositions
|
||||
// var current = dest.CompositionAliases().ToArray();
|
||||
// var proposed = source.CompositeContentTypes;
|
||||
|
||||
// var remove = current.Where(x => proposed.Contains(x) == false);
|
||||
// var add = proposed.Where(x => current.Contains(x) == false);
|
||||
|
||||
// foreach (var rem in remove)
|
||||
// dest.RemoveContentType(rem);
|
||||
|
||||
// foreach (var a in add)
|
||||
// {
|
||||
// //TODO: Remove N+1 lookup
|
||||
// var addCt = applicationContext.Services.MemberTypeService.Get(a);
|
||||
// if (addCt != null)
|
||||
// dest.AddContentType(addCt);
|
||||
// }
|
||||
// });
|
||||
|
||||
|
||||
//config.CreateMap<ContentTypeCompositionDisplay, IMediaType>()
|
||||
// //do the base mapping
|
||||
// .MapBaseContentTypeSaveToEntity(applicationContext)
|
||||
// .AfterMap((source, dest) =>
|
||||
// {
|
||||
// //sync compositions
|
||||
// var current = dest.CompositionAliases().ToArray();
|
||||
// var proposed = source.CompositeContentTypes;
|
||||
|
||||
// var remove = current.Where(x => proposed.Contains(x) == false);
|
||||
// var add = proposed.Where(x => current.Contains(x) == false);
|
||||
|
||||
// foreach (var rem in remove)
|
||||
// dest.RemoveContentType(rem);
|
||||
|
||||
// foreach (var a in add)
|
||||
// {
|
||||
// //TODO: Remove N+1 lookup
|
||||
// var addCt = applicationContext.Services.ContentTypeService.GetMediaType(a);
|
||||
// if (addCt != null)
|
||||
// dest.AddContentType(addCt);
|
||||
// }
|
||||
// });
|
||||
config.CreateMap<ContentTypeSave, IMediaType>()
|
||||
//do the base mapping
|
||||
.MapBaseContentTypeSaveToEntity(applicationContext)
|
||||
.ConstructUsing((source) => new MediaType(source.ParentId))
|
||||
.AfterMap((source, dest) =>
|
||||
{
|
||||
ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext);
|
||||
});
|
||||
|
||||
config.CreateMap<ContentTypeSave, IMemberType>()
|
||||
//do the base mapping
|
||||
.MapBaseContentTypeSaveToEntity(applicationContext)
|
||||
.ConstructUsing((source) => new MemberType(source.ParentId))
|
||||
.AfterMap((source, dest) =>
|
||||
{
|
||||
ContentTypeModelMapperExtensions.AfterMapContentTypeSaveToEntity(source, dest, applicationContext);
|
||||
});
|
||||
|
||||
config.CreateMap<IContentTypeComposition, string>().ConvertUsing(x => x.Alias);
|
||||
|
||||
|
||||
config.CreateMap<IMemberType, ContentTypeCompositionDisplay>()
|
||||
//map base logic
|
||||
.MapBaseContentTypeEntityToDisplay(applicationContext, _propertyEditorResolver);
|
||||
@@ -151,7 +95,6 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.MapBaseContentTypeEntityToDisplay(applicationContext, _propertyEditorResolver)
|
||||
.AfterMap((source, dest) =>
|
||||
{
|
||||
|
||||
//default listview
|
||||
dest.ListViewEditorName = Constants.Conventions.DataTypes.ListViewPrefix + "Media";
|
||||
|
||||
@@ -224,15 +167,13 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
#region *** Used for mapping on top of an existing display object from a save object ***
|
||||
|
||||
config.CreateMap<ContentTypeSave, ContentTypeCompositionDisplay>()
|
||||
.MapBaseContentTypeSaveToDisplay();
|
||||
|
||||
config.CreateMap<ContentTypeSave, ContentTypeDisplay>()
|
||||
.ForMember(dto => dto.CreateDate, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.UpdateDate, expression => expression.Ignore())
|
||||
.MapBaseContentTypeSaveToDisplay()
|
||||
.ForMember(dto => dto.AllowedTemplates, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.DefaultTemplate, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.ListViewEditorName, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.AvailableCompositeContentTypes, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Notifications, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Errors, expression => expression.Ignore())
|
||||
.AfterMap((source, dest) =>
|
||||
{
|
||||
//sync templates
|
||||
|
||||
@@ -19,6 +19,48 @@ namespace Umbraco.Web.Models.Mapping
|
||||
/// </remarks>
|
||||
internal static class ContentTypeModelMapperExtensions
|
||||
{
|
||||
|
||||
public static void AfterMapContentTypeSaveToEntity<TSource, TDestination>(
|
||||
TSource source, TDestination dest,
|
||||
ApplicationContext applicationContext)
|
||||
where TSource : ContentTypeSave
|
||||
where TDestination : IContentTypeComposition
|
||||
{
|
||||
//sync compositions
|
||||
var current = dest.CompositionAliases().ToArray();
|
||||
var proposed = source.CompositeContentTypes;
|
||||
|
||||
var remove = current.Where(x => proposed.Contains(x) == false);
|
||||
var add = proposed.Where(x => current.Contains(x) == false);
|
||||
|
||||
foreach (var rem in remove)
|
||||
{
|
||||
dest.RemoveContentType(rem);
|
||||
}
|
||||
|
||||
foreach (var a in add)
|
||||
{
|
||||
//TODO: Remove N+1 lookup
|
||||
var addCt = applicationContext.Services.ContentTypeService.GetContentType(a);
|
||||
if (addCt != null)
|
||||
dest.AddContentType(addCt);
|
||||
}
|
||||
}
|
||||
|
||||
public static IMappingExpression<TSource, TDestination> MapBaseContentTypeSaveToDisplay<TSource, TDestination>(
|
||||
this IMappingExpression<TSource, TDestination> mapping)
|
||||
where TSource : ContentTypeSave
|
||||
where TDestination : ContentTypeCompositionDisplay
|
||||
{
|
||||
return mapping
|
||||
.ForMember(dto => dto.CreateDate, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.UpdateDate, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.ListViewEditorName, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.AvailableCompositeContentTypes, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Notifications, expression => expression.Ignore())
|
||||
.ForMember(dto => dto.Errors, expression => expression.Ignore());
|
||||
}
|
||||
|
||||
public static IMappingExpression<TSource, TDestination> MapBaseContentTypeEntityToDisplay<TSource, TDestination>(
|
||||
this IMappingExpression<TSource, TDestination> mapping, ApplicationContext applicationContext, Lazy<PropertyEditorResolver> propertyEditorResolver)
|
||||
where TSource : IContentTypeComposition
|
||||
|
||||
Reference in New Issue
Block a user