+
+
+
+
+
- *
@@ -36,10 +39,13 @@
-
-
+
- {{saveVariantSelectorForm.saveVariantSelector.errorMsg}}
+ {{saveVariantSelectorForm.saveVariantSelector.errorMsg}}
+
+
+ {{saveVariantSelectorForm.saveInvariant.errorMsg}}
diff --git a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js
index f41f22a1a9..88d112e2d6 100644
--- a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js
@@ -2,29 +2,29 @@
* @ngdoc controller
* @name Umbraco.Editors.Media.EditController
* @function
- *
+ *
* @description
* The controller for the media editor
*/
-function mediaEditController($scope, $routeParams, $location, $http, $q, appState, mediaResource,
- entityResource, navigationService, notificationsService, localizationService,
- serverValidationManager, contentEditingHelper, fileManager, formHelper,
+function mediaEditController($scope, $routeParams, $location, $http, $q, appState, mediaResource,
+ entityResource, navigationService, notificationsService, localizationService,
+ serverValidationManager, contentEditingHelper, fileManager, formHelper,
editorState, umbRequestHelper, eventsService) {
-
+
var evts = [];
var nodeId = null;
var create = false;
var infiniteMode = $scope.model && $scope.model.infiniteMode;
- // when opening the editor through infinite editing get the
+ // when opening the editor through infinite editing get the
// node id from the model instead of the route param
if(infiniteMode && $scope.model.id) {
nodeId = $scope.model.id;
} else {
nodeId = $routeParams.id;
}
-
- // when opening the editor through infinite editing get the
+
+ // when opening the editor through infinite editing get the
// create option from the model instead of the route param
if(infiniteMode) {
create = $scope.model.create;
@@ -72,22 +72,22 @@ function mediaEditController($scope, $routeParams, $location, $http, $q, appStat
}
function init() {
-
+
var content = $scope.content;
-
+
// we need to check whether an app is present in the current data, if not we will present the default app.
var isAppPresent = false;
-
+
// on first init, we dont have any apps. but if we are re-initializing, we do, but ...
if ($scope.app) {
-
+
// lets check if it still exists as part of our apps array. (if not we have made a change to our docType, even just a re-save of the docType it will turn into new Apps.)
content.apps.forEach(app => {
if (app === $scope.app) {
isAppPresent = true;
}
});
-
+
// if we did reload our DocType, but still have the same app we will try to find it by the alias.
if (isAppPresent === false) {
content.apps.forEach(app => {
@@ -98,9 +98,9 @@ function mediaEditController($scope, $routeParams, $location, $http, $q, appStat
}
});
}
-
+
}
-
+
// if we still dont have a app, lets show the first one:
if (isAppPresent === false) {
content.apps[0].active = true;
@@ -108,16 +108,16 @@ function mediaEditController($scope, $routeParams, $location, $http, $q, appStat
}
editorState.set($scope.content);
-
+
bindEvents();
}
-
+
function bindEvents() {
//bindEvents can be called more than once and we don't want to have multiple bound events
for (var e in evts) {
eventsService.unsubscribe(evts[e]);
}
-
+
evts.push(eventsService.on("editors.mediaType.saved", function(name, args) {
// if this media item uses the updated media type we need to reload the media item
if(args && args.mediaType && args.mediaType.key === $scope.content.contentType.key) {
@@ -131,7 +131,7 @@ function mediaEditController($scope, $routeParams, $location, $http, $q, appStat
}));
}
$scope.page.submitButtonLabelKey = "buttons_save";
-
+
/** Syncs the content item to it's tree node - this occurs on first load and after saving */
function syncTreeNode(content, path, initialLoad) {
@@ -149,7 +149,7 @@ function mediaEditController($scope, $routeParams, $location, $http, $q, appStat
//it's a child item, just sync the ui node to the parent
navigationService.syncTree({ tree: "media", path: path.substring(0, path.lastIndexOf(",")).split(","), forceReload: initialLoad !== true });
- //if this is a child of a list view and it's the initial load of the editor, we need to get the tree node
+ //if this is a child of a list view and it's the initial load of the editor, we need to get the tree node
// from the server so that we can load in the actions menu.
umbRequestHelper.resourcePromise(
$http.get(content.treeNodeUrl),
@@ -176,7 +176,7 @@ function mediaEditController($scope, $routeParams, $location, $http, $q, appStat
$scope.save = function () {
if (formHelper.submitForm({ scope: $scope })) {
-
+
$scope.page.saveButtonState = "busy";
mediaResource.save($scope.content, create, fileManager.getFiles())
@@ -200,12 +200,16 @@ function mediaEditController($scope, $routeParams, $location, $http, $q, appStat
editorState.set($scope.content);
syncTreeNode($scope.content, data.path);
-
+
$scope.page.saveButtonState = "success";
init();
}
+ eventsService.emit("editors.media.saved", {media: data});
+
+ return data;
+
}, function(err) {
formHelper.resetForm({ scope: $scope, hasErrors: true });
@@ -213,16 +217,16 @@ function mediaEditController($scope, $routeParams, $location, $http, $q, appStat
err: err,
rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, err.data)
});
-
+
editorState.set($scope.content);
$scope.page.saveButtonState = "error";
});
}
else {
- showValidationNotification();
+ showValidationNotification();
}
-
+
};
function loadMedia() {
@@ -231,7 +235,7 @@ function mediaEditController($scope, $routeParams, $location, $http, $q, appStat
.then(function (data) {
$scope.content = data;
-
+
if (data.isChildOfListView && data.trashed === false) {
$scope.page.listViewPath = ($routeParams.page)
? "/media/media/edit/" + data.parentId + "?page=" + $routeParams.page
@@ -247,9 +251,9 @@ function mediaEditController($scope, $routeParams, $location, $http, $q, appStat
serverValidationManager.notifyAndClearAllSubscriptions();
if(!infiniteMode) {
- syncTreeNode($scope.content, data.path, true);
+ syncTreeNode($scope.content, data.path, true);
}
-
+
if ($scope.content.parentId && $scope.content.parentId !== -1 && $scope.content.parentId !== -21) {
//We fetch all ancestors of the node to generate the footer breadcrump navigation
entityResource.getAncestors(nodeId, "media")
@@ -279,7 +283,7 @@ function mediaEditController($scope, $routeParams, $location, $http, $q, appStat
$scope.appChanged = function (app) {
$scope.app = app;
-
+
// setup infinite mode
if(infiniteMode) {
$scope.page.submitButtonLabelKey = "buttons_saveAndClose";
@@ -296,7 +300,7 @@ function mediaEditController($scope, $routeParams, $location, $http, $q, appStat
$location.path($scope.page.listViewPath.split("?")[0]);
}
};
-
+
//ensure to unregister from all events!
$scope.$on('$destroy', function () {
for (var e in evts) {
diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/numberrange.html b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/numberrange.html
index d9d8cad982..6e67c94793 100644
--- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/numberrange.html
+++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/numberrange.html
@@ -4,6 +4,7 @@
type="number"
ng-model="model.value.min"
placeholder="0"
+ min="0"
ng-max="model.value.max"
fix-number />
–
@@ -11,7 +12,7 @@
type="number"
ng-model="model.value.max"
placeholder="∞"
- ng-min="model.value.min"
+ ng-min="model.value.min || 0"
fix-number />
diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesourcetypepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesourcetypepicker.controller.js
index dcc9add395..d02e626bfa 100644
--- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesourcetypepicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesourcetypepicker.controller.js
@@ -99,6 +99,11 @@ function TreeSourceTypePickerController($scope, contentTypeResource, mediaTypeRe
eventsService.unsubscribe(evts[e]);
}
});
+
+ if ($scope.model.config.itemType) {
+ currentItemType = $scope.model.config.itemType;
+ init();
+ }
}
angular.module('umbraco').controller("Umbraco.PrevalueEditors.TreeSourceTypePickerController", TreeSourceTypePickerController);
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.less
index 45a4c08598..ffadc21866 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.less
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.less
@@ -60,8 +60,14 @@
ng-form.ng-invalid-val-server-match-content > .umb-block-list__block > .umb-block-list__block--content > div > & {
> button {
color: @formErrorText;
+ .show-validation-type-warning & {
+ color: @formWarningText;
+ }
span.caret {
border-top-color: @formErrorText;
+ .show-validation-type-warning & {
+ border-top-color: @formWarningText;
+ }
}
}
}
@@ -84,6 +90,9 @@
padding: 2px;
line-height: 10px;
background-color: @formErrorText;
+ .show-validation-type-warning & {
+ background-color: @formWarningText;
+ }
font-weight: 900;
animation-duration: 1.4s;
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.less
index 613a47b926..837fd3f564 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.less
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.less
@@ -42,6 +42,9 @@
ng-form.ng-invalid-val-server-match-content > .umb-block-list__block > .umb-block-list__block--content > div > & {
color: @formErrorText;
+ .show-validation-type-warning & {
+ color: @formWarningText;
+ }
}
ng-form.ng-invalid-val-server-match-content > .umb-block-list__block:not(.--active) > .umb-block-list__block--content > div > & {
> span {
@@ -61,6 +64,9 @@
padding: 2px;
line-height: 10px;
background-color: @formErrorText;
+ .show-validation-type-warning & {
+ background-color: @formWarningText;
+ }
font-weight: 900;
animation-duration: 1.4s;
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less
index 019a772fdd..47b1d00ca2 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less
@@ -10,7 +10,7 @@
.umb-block-list__wrapper {
position: relative;
- max-width: 1024px;
+ .umb-property-editor--limit-width();
> .ui-sortable > .ui-sortable-helper > .umb-block-list__block > .umb-block-list__block--content > * {
box-shadow: 0px 5px 10px 0 rgba(0,0,0,.2);
}
@@ -23,10 +23,6 @@
> .umb-block-list__block--actions {
opacity: 0;
transition: opacity 120ms;
-
- .--error {
- color: @formErrorBorder !important;
- }
}
&:hover,
@@ -100,6 +96,12 @@ ng-form.ng-invalid-val-server-match-settings > .umb-block-list__block > .umb-blo
&:hover {
color: @ui-action-discreet-type-hover;
}
+ &.--error {
+ color: @errorBackground;
+ .show-validation-type-warning & {
+ color: @warningBackground;
+ }
+ }
> .__error-badge {
position: absolute;
top: -2px;
@@ -113,7 +115,10 @@ ng-form.ng-invalid-val-server-match-settings > .umb-block-list__block > .umb-blo
font-weight: bold;
padding: 2px;
line-height: 8px;
- background-color: @red;
+ background-color: @errorBackground;
+ .show-validation-type-warning & {
+ background-color: @warningBackground;
+ }
display: none;
font-weight: 900;
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js
index 2d9b13ec7a..7334fbeadf 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js
@@ -55,6 +55,12 @@
vm.supportCopy = clipboardService.isSupported();
vm.clipboardItems = [];
unsubscribe.push(eventsService.on("clipboardService.storageUpdate", updateClipboard));
+ unsubscribe.push($scope.$on("editors.content.splitViewChanged", (event, eventData) => {
+ var compositeId = vm.umbVariantContent.editor.compositeId;
+ if(eventData.editors.some(x => x.compositeId === compositeId)) {
+ updateAllBlockObjects();
+ }
+ }));
vm.layout = []; // The layout object specific to this Block Editor, will be a direct reference from Property Model.
vm.availableBlockTypes = []; // Available block entries of this property editor.
@@ -66,6 +72,7 @@
});
vm.$onInit = function() {
+
if (vm.umbProperty && !vm.umbVariantContent) {// if we dont have vm.umbProperty, it means we are in the DocumentTypeEditor.
// not found, then fallback to searching the scope chain, this may be needed when DOM inheritance isn't maintained but scope
// inheritance is (i.e.infinite editing)
@@ -175,6 +182,8 @@
// is invalid for some reason or the data structure has changed.
invalidLayoutItems.push(entry);
}
+ } else {
+ updateBlockObject(entry.$block);
}
});
@@ -197,6 +206,16 @@
}
+ function updateAllBlockObjects() {
+ // Update the blockObjects in our layout.
+ vm.layout.forEach(entry => {
+ // $block must have the data property to be a valid BlockObject, if not its considered as a destroyed blockObject.
+ if (entry.$block) {
+ updateBlockObject(entry.$block);
+ }
+ });
+ }
+
function getDefaultViewForBlock(block) {
var defaultViewFolderPath = "views/propertyeditors/blocklist/blocklistentryeditors/";
@@ -237,9 +256,6 @@
if (block === null) return null;
- ensureCultureData(block.content);
- ensureCultureData(block.settings);
-
block.view = (block.config.view ? block.config.view : getDefaultViewForBlock(block));
block.showValidation = block.config.view ? true : false;
@@ -254,20 +270,51 @@
block.setParentForm = function (parentForm) {
this._parentForm = parentForm;
};
- block.activate = activateBlock.bind(null, block);
- block.edit = function () {
+
+ /** decorator methods, to enable switching out methods without loosing references that would have been made in Block Views codes */
+ block.activate = function() {
+ this._activate();
+ };
+ block.edit = function() {
+ this._edit();
+ };
+ block.editSettings = function() {
+ this._editSettings();
+ };
+ block.requestDelete = function() {
+ this._requestDelete();
+ };
+ block.delete = function() {
+ this._delete();
+ };
+ block.copy = function() {
+ this._copy();
+ };
+ updateBlockObject(block);
+
+ return block;
+ }
+
+ /** As the block object now contains references to this instance of a property editor, we need to ensure that the Block Object contains latest references.
+ * This is a bit hacky but the only way to maintain this reference currently.
+ * Notice this is most relevant for invariant properties on variant documents, specially for the scenario where the scope of the reference we stored is destroyed, therefor we need to ensure we always have references to a current running property editor*/
+ function updateBlockObject(block) {
+
+ ensureCultureData(block.content);
+ ensureCultureData(block.settings);
+
+ block._activate = activateBlock.bind(null, block);
+ block._edit = function () {
var blockIndex = vm.layout.indexOf(this.layout);
editBlock(this, false, blockIndex, this._parentForm);
};
- block.editSettings = function () {
+ block._editSettings = function () {
var blockIndex = vm.layout.indexOf(this.layout);
editBlock(this, true, blockIndex, this._parentForm);
};
- block.requestDelete = requestDeleteBlock.bind(null, block);
- block.delete = deleteBlock.bind(null, block);
- block.copy = copyBlock.bind(null, block);
-
- return block;
+ block._requestDelete = requestDeleteBlock.bind(null, block);
+ block._delete = deleteBlock.bind(null, block);
+ block._copy = copyBlock.bind(null, block);
}
function addNewBlock(index, contentElementTypeKey) {
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js
index 71e334aee2..4f1016e680 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js
@@ -11,11 +11,14 @@
*
*/
function fileUploadController($scope, fileManager) {
-
+
$scope.fileChanged = onFileChanged;
//declare a special method which will be called whenever the value has changed from the server
$scope.model.onValueChanged = onValueChanged;
+
+ $scope.fileExtensionsString = $scope.model.config.fileExtensions ? $scope.model.config.fileExtensions.map(x => "."+x.value).join(",") : "";
+
/**
* Called when the file selection value changes
* @param {any} value
@@ -38,9 +41,34 @@
files: []
});
}
-
+
};
angular.module("umbraco")
- .controller('Umbraco.PropertyEditors.FileUploadController', fileUploadController);
+ .controller('Umbraco.PropertyEditors.FileUploadController', fileUploadController)
+ .run(function (mediaHelper) {
+ if (mediaHelper && mediaHelper.registerFileResolver) {
+
+ //NOTE: The 'entity' can be either a normal media entity or an "entity" returned from the entityResource
+ // they contain different data structures so if we need to query against it we need to be aware of this.
+ mediaHelper.registerFileResolver("Umbraco.UploadField", function (property, entity, thumbnail) {
+ if (thumbnail) {
+ if (mediaHelper.detectIfImageByExtension(property.value)) {
+ //get default big thumbnail from image processor
+ var thumbnailUrl = property.value + "?rnd=" + moment(entity.updateDate).format("YYYYMMDDHHmmss") + "&width=500&animationprocessmode=first";
+ return thumbnailUrl;
+ }
+ else {
+ return null;
+ }
+ }
+ else {
+ return property.value;
+ }
+ });
+
+ }
+ });
+
+
})();
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.html
index 522278e99e..36509e8947 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.html
@@ -4,6 +4,7 @@
property-alias="{{model.alias}}"
value="model.value"
required="model.validation.mandatory"
- on-files-selected="fileChanged(value)">
+ on-files-selected="fileChanged(value)"
+ accept-file-ext="fileExtensionsString">
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js
index cf201976ad..fdf70693b2 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js
@@ -4,10 +4,37 @@ angular.module("umbraco")
var vm = this;
+ vm.toggleAllowed = toggleAllowed;
+ vm.configureSection = configureSection;
+ vm.deleteSection = deleteSection;
+ vm.selectRow = selectRow;
+ vm.percentage = percentage;
+ vm.scaleUp = scaleUp;
+ vm.scaleDown = scaleDown;
+ vm.close = close;
+ vm.submit = submit;
+
vm.labels = {};
function init() {
+ $scope.currentLayout = $scope.model.currentLayout;
+ $scope.columns = $scope.model.columns;
+ $scope.rows = $scope.model.rows;
+ $scope.currentSection = null;
+
+ // Setup copy of rows on sections
+ if ($scope.currentLayout && $scope.currentLayout.sections) {
+ $scope.currentLayout.sections.forEach(section => {
+ section.rows = Utilities.copy($scope.rows);
+
+ // Check if rows are selected
+ section.rows.forEach(row => {
+ row.selected = section.allowed && section.allowed.includes(row.name);
+ });
+ });
+ }
+
var labelKeys = [
"grid_addGridLayout",
"grid_allowAllRowConfigurations"
@@ -28,46 +55,43 @@ angular.module("umbraco")
}
}
- $scope.currentLayout = $scope.model.currentLayout;
- $scope.columns = $scope.model.columns;
- $scope.rows = $scope.model.rows;
- $scope.currentSection = undefined;
-
- $scope.scaleUp = function(section, max, overflow){
+ function scaleUp(section, max, overflow){
var add = 1;
- if(overflow !== true){
- add = (max > 1) ? 1 : max;
+ if (overflow !== true){
+ add = (max > 1) ? 1 : max;
}
//var add = (max > 1) ? 1 : max;
section.grid = section.grid+add;
- };
+ }
- $scope.scaleDown = function(section){
+ function scaleDown(section){
var remove = (section.grid > 1) ? 1 : 0;
section.grid = section.grid-remove;
- };
+ }
- $scope.percentage = function(spans){
+ function percentage(spans){
return ((spans / $scope.columns) * 100).toFixed(8);
- };
+ }
/****************
Section
*****************/
- $scope.configureSection = function(section, template){
- if(section === undefined){
+ function configureSection(section, template) {
+ if (section === null || section === undefined) {
var space = ($scope.availableLayoutSpace > 4) ? 4 : $scope.availableLayoutSpace;
section = {
- grid: space
+ grid: space,
+ rows: Utilities.copy($scope.rows)
};
template.sections.push(section);
- }
-
- $scope.currentSection = section;
- $scope.currentSection.allowAll = section.allowAll || !section.allowed || !section.allowed.length;
- };
+ }
- $scope.toggleAllowed = function (section) {
+ section.allowAll = section.allowAll || !section.allowed || !section.allowed.length;
+
+ $scope.currentSection = section;
+ }
+
+ function toggleAllowed(section) {
section.allowAll = !section.allowAll;
if (section.allowed) {
@@ -76,21 +100,22 @@ angular.module("umbraco")
else {
section.allowed = [];
}
- };
+ }
- $scope.deleteSection = function(section, template) {
+ function deleteSection(section, template) {
if ($scope.currentSection === section) {
- $scope.currentSection = undefined;
+ $scope.currentSection = null;
}
var index = template.sections.indexOf(section)
template.sections.splice(index, 1);
- };
+ }
+
+ function selectRow(section, row) {
- $scope.selectRow = function (section, row) {
section.allowed = section.allowed || [];
var index = section.allowed.indexOf(row.name);
- if (row.allowed === true) {
+ if (row.selected === true) {
if (index === -1) {
section.allowed.push(row.name);
}
@@ -98,22 +123,32 @@ angular.module("umbraco")
else {
section.allowed.splice(index, 1);
}
- };
+ }
- $scope.close = function() {
+ function close() {
if ($scope.model.close) {
+ cleanUpRows();
$scope.model.close();
}
- };
+ }
- $scope.submit = function () {
+ function submit() {
if ($scope.model.submit) {
+ cleanUpRows();
$scope.model.submit($scope.currentLayout);
}
- };
+ }
+
+ function cleanUpRows () {
+ $scope.currentLayout.sections.forEach(section => {
+ if (section.rows) {
+ delete section.rows;
+ }
+ });
+ }
$scope.$watch("currentLayout", function(layout){
- if(layout){
+ if (layout) {
var total = 0;
_.forEach(layout.sections, function(section){
total = (total + section.grid);
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html
index 6ff18e83ad..5e05f56b48 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html
@@ -34,38 +34,37 @@