diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js index 9fbbad8f09..099439fa4b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js @@ -10,7 +10,7 @@ (function () { "use strict"; - function DataTypeSettingsController($scope, dataTypeResource, dataTypeHelper, localizationService) { + function DataTypeSettingsController($scope, dataTypeResource, dataTypeHelper, localizationService, notificationsService, overlayService, formHelper) { var vm = this; @@ -102,7 +102,7 @@ vm.saveButtonState = "busy"; var preValues = dataTypeHelper.createPreValueProps(vm.dataType.preValues); - + dataTypeResource.save(vm.dataType, preValues, $scope.model.create).then(function(newDataType) { $scope.model.dataType = newDataType; vm.saveButtonState = "success"; @@ -110,6 +110,19 @@ if ($scope.model && $scope.model.submit) { $scope.model.submit($scope.model); } + }, function(err) { + vm.saveButtonState = "error"; + + if(err.status === 400) { + if (err.data && (err.data.ModelState)) { + + formHelper.handleServerValidation(err.data.ModelState); + + for (var e in err.data.ModelState) { + notificationsService.error("Validation", err.data.ModelState[e][0]); + } + } + } }); } @@ -120,4 +133,4 @@ angular.module("umbraco").controller("Umbraco.Editors.DataTypeSettingsController", DataTypeSettingsController); -})(); \ No newline at end of file +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.controller.js index 2a00df32dc..19057fa842 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.controller.js @@ -96,7 +96,7 @@ angular.module("umbraco") $scope.layoutConfigOverlay.rows = $scope.model.value.layouts; $scope.layoutConfigOverlay.columns = $scope.model.value.columns; $scope.layoutConfigOverlay.show = true; - + $scope.layoutConfigOverlay.submit = function(model) { $scope.layoutConfigOverlay.show = false; $scope.layoutConfigOverlay = null; @@ -218,8 +218,8 @@ angular.module("umbraco") $scope.editConfigCollectionOverlay.show = true; $scope.editConfigCollectionOverlay.submit = function(model) { - - callback(model.config) + + callback(model.config); $scope.editConfigCollectionOverlay.show = false; $scope.editConfigCollectionOverlay = null; diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index ee2f2c313a..27d63d9d7a 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -1830,8 +1830,10 @@ namespace Umbraco.Web.Editors } if (model.ParentId < 0) { - //cannot move if the content item is not allowed at the root - if (toMove.ContentType.AllowedAsRoot == false) + //cannot move if the content item is not allowed at the root unless there are + //none allowed at root (in which case all should be allowed at root) + var contentTypeService = Services.ContentTypeService; + if (toMove.ContentType.AllowedAsRoot == false && contentTypeService.GetAll().Any(ct => ct.AllowedAsRoot)) { throw new HttpResponseException( Request.CreateNotificationValidationErrorResponse( diff --git a/src/Umbraco.Web/Editors/ContentTypeController.cs b/src/Umbraco.Web/Editors/ContentTypeController.cs index 756762a853..8a56c87ad9 100644 --- a/src/Umbraco.Web/Editors/ContentTypeController.cs +++ b/src/Umbraco.Web/Editors/ContentTypeController.cs @@ -393,7 +393,11 @@ namespace Umbraco.Web.Editors IEnumerable types; if (contentId == Constants.System.Root) { - types = Services.ContentTypeService.GetAll().Where(x => x.AllowedAsRoot).ToList(); + var allContentTypes = Services.ContentTypeService.GetAll().ToList(); + bool AllowedAsRoot(IContentType x) => x.AllowedAsRoot; + types = allContentTypes.Any(AllowedAsRoot) + ? allContentTypes.Where(AllowedAsRoot).ToList() + : allContentTypes; } else { diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index 16816aa9fc..fb6ca39289 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -870,8 +870,10 @@ namespace Umbraco.Web.Editors } if (model.ParentId < 0) { - //cannot move if the content item is not allowed at the root - if (toMove.ContentType.AllowedAsRoot == false) + //cannot move if the content item is not allowed at the root unless there are + //none allowed at root (in which case all should be allowed at root) + var mediaTypeService = Services.MediaTypeService; + if (toMove.ContentType.AllowedAsRoot == false && mediaTypeService.GetAll().Any(ct => ct.AllowedAsRoot)) { var notificationModel = new SimpleNotificationModel(); notificationModel.AddErrorNotification(Services.TextService.Localize("moveOrCopy/notAllowedAtRoot"), ""); diff --git a/src/Umbraco.Web/PropertyEditors/GridConfigurationEditor.cs b/src/Umbraco.Web/PropertyEditors/GridConfigurationEditor.cs index fe86bb9a6e..902cd5b41b 100644 --- a/src/Umbraco.Web/PropertyEditors/GridConfigurationEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/GridConfigurationEditor.cs @@ -1,4 +1,9 @@ -using Umbraco.Core.PropertyEditors; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using Newtonsoft.Json; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.PropertyEditors.Validators; namespace Umbraco.Web.PropertyEditors { @@ -6,5 +11,45 @@ namespace Umbraco.Web.PropertyEditors /// Represents the configuration for the grid value editor. /// public class GridConfigurationEditor : ConfigurationEditor - { } + { + public GridConfigurationEditor() + { + var items = Fields.First(x => x.Key == "items"); + + items.Validators.Add(new GridValidator()); + } + } + + public class GridValidator : IValueValidator + { + public IEnumerable Validate(object rawValue, string valueType, object dataTypeConfiguration) + { + if (rawValue == null) + yield break; + + var model = JsonConvert.DeserializeObject(rawValue.ToString()); + + if (model.Templates.Any(t => t.Sections.Sum(s => s.Grid) > model.Columns)) + { + yield return new ValidationResult("Columns must be at least the same size as the largest layout", new[] { nameof(model.Columns) }); + } + + } + } + + public class GridEditorModel + { + public GridEditorTemplateModel[] Templates { get; set; } + public int Columns { get; set; } + } + + public class GridEditorTemplateModel + { + public GridEditorSectionModel[] Sections { get; set; } + } + + public class GridEditorSectionModel + { + public int Grid { get; set; } + } }