diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 1df2133891..2fb2222528 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -1633,11 +1633,14 @@ namespace Umbraco.Core.Services //Check if parent is published (although not if its a root node) - if parent isn't published this Content cannot be published publishStatus.StatusType = CheckAndLogIsPublishable(content); - //Content contains invalid property values and can therefore not be published - fire event? - publishStatus.StatusType = CheckAndLogIsValid(content); - //set the invalid properties (if there are any) - publishStatus.InvalidProperties = ((ContentBase) content).LastInvalidProperties; - + //if it is not successful, then check if the props are valid + if ((int)publishStatus.StatusType < 10) + { + //Content contains invalid property values and can therefore not be published - fire event? + publishStatus.StatusType = CheckAndLogIsValid(content); + //set the invalid properties (if there are any) + publishStatus.InvalidProperties = ((ContentBase)content).LastInvalidProperties; + } //if we're still successful, then publish using the strategy if (publishStatus.StatusType == PublishStatusType.Success) { diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js index 2eee59e8a8..2f551f80a3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js @@ -53,8 +53,10 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser } //check for changed built-in properties of the content - if (!_.isEqual(origContent.name, newContent.name)) { - origContent.name = newContent.name; + for (var o in origContent) { + if (!_.isEqual(origContent[o], newContent[o])) { + origContent[o] = newContent[o]; + } } //check for changed properties of the content diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index 7f70cae8ef..80cb6c9270 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -1,206 +1,213 @@ angular.module("umbraco") - .controller("Umbraco.PropertyEditors.ListViewController", - function ($rootScope, $scope, $routeParams, contentResource, contentTypeResource, notificationsService, iconHelper) { + .controller("Umbraco.PropertyEditors.ListViewController", + function ($rootScope, $scope, $routeParams, contentResource, contentTypeResource, notificationsService, iconHelper, dialogService) { - $scope.selected = []; - $scope.actionInProgress = false; - - $scope.options = { - pageSize: 10, - pageNumber: 1, - filter: '', - orderBy: 'Id', - orderDirection: "desc" - }; + $scope.actionInProgress = false; + $scope.listViewResultSet = { + totalPages: 0, + items: [] + }; - - $scope.next = function(){ - if ($scope.options.pageNumber < $scope.listViewResultSet.totalPages) { - $scope.options.pageNumber++; + $scope.options = { + pageSize: 10, + pageNumber: 1, + filter: '', + orderBy: 'Id', + orderDirection: "desc" + }; + + + $scope.next = function () { + if ($scope.options.pageNumber < $scope.listViewResultSet.totalPages) { + $scope.options.pageNumber++; + $scope.reloadView($scope.contentId); + } + }; + + $scope.goToPage = function (pageNumber) { + $scope.options.pageNumber = pageNumber + 1; $scope.reloadView($scope.contentId); - } - }; + }; - $scope.goToPage = function (pageNumber) { - $scope.options.pageNumber = pageNumber + 1; - $scope.reloadView($scope.contentId); - }; + $scope.sort = function (field) { + + $scope.options.orderBy = field; + + + if ($scope.options.orderDirection === "desc") { + $scope.options.orderDirection = "asc"; + } else { + $scope.options.orderDirection = "desc"; + } - $scope.sort = function (field) { - - $scope.options.orderBy = field; - - - if ($scope.options.orderDirection === "desc") { - $scope.options.orderDirection = "asc"; - }else{ - $scope.options.orderDirection = "desc"; - } - - - $scope.reloadView($scope.contentId); - }; - $scope.prev = function(){ - if ($scope.options.pageNumber > 1) { - $scope.options.pageNumber--; $scope.reloadView($scope.contentId); - } - }; + }; - /*Loads the search results, based on parameters set in prev,next,sort and so on*/ - /*Pagination is done by an array of objects, due angularJS's funky way of monitoring state - with simple values */ + $scope.prev = function () { + if ($scope.options.pageNumber > 1) { + $scope.options.pageNumber--; + $scope.reloadView($scope.contentId); + } + }; + + /*Loads the search results, based on parameters set in prev,next,sort and so on*/ + /*Pagination is done by an array of objects, due angularJS's funky way of monitoring state + with simple values */ + + $scope.reloadView = function (id) { + contentResource.getChildren(id, $scope.options).then(function (data) { + + $scope.listViewResultSet = data; + $scope.pagination = []; + + for (var i = $scope.listViewResultSet.totalPages - 1; i >= 0; i--) { + $scope.pagination[i] = { index: i, name: i + 1 }; + } + + if ($scope.options.pageNumber > $scope.listViewResultSet.totalPages) { + $scope.options.pageNumber = $scope.listViewResultSet.totalPages; + } + + }); + }; + + $scope.selectAll = function ($event) { + var checkbox = $event.target; + + for (var i = 0; i < $scope.listViewResultSet.items.length; i++) { + var entity = $scope.listViewResultSet.items[i]; + entity.selected = checkbox.checked; + } + }; + + $scope.isSelectedAll = function () { + return _.every($scope.listViewResultSet.items, function (item) { + return item.selected; + }); + }; + + $scope.isAnythingSelected = function () { + return _.some($scope.listViewResultSet.items, function (item) { + return item.selected; + }); + }; + + $scope.getIcon = function (entry) { + return iconHelper.convertFromLegacyIcon(entry.icon); + }; + + $scope.delete = function () { + var selected = _.filter($scope.listViewResultSet.items, function (item) { + return item.selected; + }); + var total = selected.length; + if (total === 0) { + return; + } + + if (confirm("Sure you want to delete?") == true) { + $scope.actionInProgress = true; + $scope.bulkStatus = "Starting with delete"; + var current = 1; + + for (var i = 0; i < selected.length; i++) { + $scope.bulkStatus = "Deleted doc " + current + " out of " + total + " documents"; + contentResource.deleteById(selected[i].id).then(function (data) { + if (current === total) { + notificationsService.success("Bulk action", "Deleted " + total + "documents"); + $scope.bulkStatus = ""; + $scope.reloadView($scope.contentId); + $scope.actionInProgress = false; + } + current++; + }); + } + } + + }; + + $scope.publish = function () { + var selected = _.filter($scope.listViewResultSet.items, function (item) { + return item.selected; + }); + var total = selected.length; + if (total === 0) { + return; + } - $scope.reloadView = function(id) { - contentResource.getChildren(id, $scope.options).then(function(data) { - - $scope.listViewResultSet = data; - $scope.pagination = []; - - for (var i = $scope.listViewResultSet.totalPages - 1; i >= 0; i--) { - $scope.pagination[i] = { index: i, name: i + 1 }; - } - - if ($scope.options.pageNumber > $scope.listViewResultSet.totalPages) { - $scope.options.pageNumber = $scope.listViewResultSet.totalPages; - } - - }); - }; - - var updateSelected = function (action, id) { - if (action === 'add' && $scope.selected.indexOf(id) === -1) { - $scope.selected.push(id); - } - if (action === 'remove' && $scope.selected.indexOf(id) !== -1) { - $scope.selected.splice($scope.selected.indexOf(id), 1); - } - }; - - $scope.updateSelection = function ($event, item) { - if(item.selected){ - item.selected = false; - var index = $scope.selected.indexOf(item.id); - if(index){ - $scope.selected.splice(index, 1); - } - }else{ - item.selected = true; - $scope.selected.push(item.id); - } - }; - - $scope.selectAll = function ($event) { - var checkbox = $event.target; - var action = (checkbox.checked ? 'add' : 'remove'); - - for (var i = 0; i < $scope.listViewResultSet.items.length; i++) { - var entity = $scope.listViewResultSet.items[i]; - entity.selected = checkbox.checked; - updateSelected(action, entity.id); - } - }; - - $scope.getSelectedClass = function (entity) { - return $scope.isSelected(entity.id) ? 'selected' : ''; - }; - - $scope.isSelected = function (id) { - return $scope.selected.indexOf(id) >= 0; - }; - - $scope.isSelectedAll = function () { - if ($scope.listViewResultSet != null) - return $scope.selected.length === $scope.listViewResultSet.items.length; - else - return false; - }; - - $scope.isAnythingSelected = function() { - return $scope.selected.length > 0; - }; - - $scope.getIcon = function(entry){ - return iconHelper.convertFromLegacyIcon(entry.icon); - }; - - $scope.delete = function () { - - if (confirm("Sure you want to delete?") == true) { $scope.actionInProgress = true; - $scope.bulkStatus = "Starting with delete"; + $scope.bulkStatus = "Starting with publish"; var current = 1; - var total = $scope.selected.length; - for (var i = 0; i < $scope.selected.length; i++) { - $scope.bulkStatus = "Deleted doc " + current + " out of " + total + " documents"; - contentResource.deleteById($scope.selected[i]).then(function(data) { - if (current == total) { - notificationsService.success("Bulk action", "Deleted " + total + "documents"); + + for (var i = 0; i < selected.length; i++) { + $scope.bulkStatus = "Publishing " + current + " out of " + total + " documents"; + + contentResource.publishById(selected[i].id) + .then(function (content) { + if (current == total) { + notificationsService.success("Bulk action", "Published " + total + "documents"); + $scope.bulkStatus = ""; + $scope.reloadView($scope.contentId); + $scope.actionInProgress = false; + } + current++; + }, function (err) { + $scope.bulkStatus = ""; - $scope.selected = []; $scope.reloadView($scope.contentId); $scope.actionInProgress = false; - } - current++; - }); + + //if there are validation errors for publishing then we need to show them + if (err.status === 400 && err.data && err.data.Message) { + notificationsService.error("Publish error", err.data.Message); + } + else { + dialogService.ysodDialog(err); + } + }); + } + }; + + $scope.unpublish = function () { + var selected = _.filter($scope.listViewResultSet.items, function (item) { + return item.selected; + }); + var total = selected.length; + if (total === 0) { + return; + } + + $scope.actionInProgress = true; + $scope.bulkStatus = "Starting with publish"; + var current = 1; + + for (var i = 0; i < selected.length; i++) { + $scope.bulkStatus = "Unpublishing " + current + " out of " + total + " documents"; + + contentResource.unPublish(selected[i].id) + .then(function (content) { + + if (current == total) { + notificationsService.success("Bulk action", "Published " + total + "documents"); + $scope.bulkStatus = ""; + $scope.reloadView($scope.contentId); + $scope.actionInProgress = false; + } + + current++; + }); + } + }; + + if ($routeParams.id) { + $scope.pagination = new Array(100); + $scope.listViewAllowedTypes = contentTypeResource.getAllowedTypes($routeParams.id); + $scope.reloadView($routeParams.id); + + $scope.contentId = $routeParams.id; + } - }; - - $scope.publish = function () { - $scope.actionInProgress = true; - $scope.bulkStatus = "Starting with publish"; - var current = 1; - var total = $scope.selected.length; - for (var i = 0; i < $scope.selected.length; i++) { - $scope.bulkStatus = "Publishing " + current + " out of " + total + " documents"; - - contentResource.publishById($scope.selected[i]) - .then(function(content){ - if (current == total) { - notificationsService.success("Bulk action", "Published " + total + "documents"); - $scope.bulkStatus = ""; - $scope.reloadView($scope.contentId); - $scope.actionInProgress = false; - } - current++; - }); - - } - }; - - $scope.unpublish = function () { - $scope.actionInProgress = true; - $scope.bulkStatus = "Starting with publish"; - var current = 1; - var total = $scope.selected.length; - for (var i = 0; i < $scope.selected.length; i++) { - $scope.bulkStatus = "Unpublishing " + current + " out of " + total + " documents"; - - contentResource.unPublish($scope.selected[i]) - .then(function(content){ - - if (current == total) { - notificationsService.success("Bulk action", "Published " + total + "documents"); - $scope.bulkStatus = ""; - $scope.reloadView($scope.contentId); - $scope.actionInProgress = false; - } - - current++; - }); - } - }; - - if ($routeParams.id) { - $scope.pagination = new Array(100); - $scope.listViewAllowedTypes = contentTypeResource.getAllowedTypes($routeParams.id); - $scope.reloadView($routeParams.id); - - $scope.contentId = $routeParams.id; - - } - -}); + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index dfd82c01f8..e689071c03 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -31,8 +31,8 @@ - - + +
@@ -53,8 +53,7 @@ +
- {{result.name}} {{result.updateDate|date:'medium'}} diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 8d067b9643..8cc2c26bd3 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -309,7 +309,34 @@ namespace Umbraco.Web.Editors return HandleContentNotFound(id, false); } - Services.ContentService.Publish(foundContent, UmbracoUser.Id); + var publishResult = Services.ContentService.PublishWithStatus(foundContent, UmbracoUser.Id); + if (publishResult.Success == false) + { + switch (publishResult.Result.StatusType) + { + case PublishStatusType.FailedPathNotPublished: + return Request.CreateValidationErrorResponse( + ui.Text("publish", "contentPublishedFailedByParent", + string.Format("{0} ({1})", publishResult.Result.ContentItem.Name, publishResult.Result.ContentItem.Id), + Security.CurrentUser).Trim()); + case PublishStatusType.FailedCancelledByEvent: + return Request.CreateValidationErrorResponse( + ui.Text("speechBubbles", "contentPublishedFailedByEvent")); + case PublishStatusType.FailedHasExpired: + case PublishStatusType.FailedAwaitingRelease: + case PublishStatusType.FailedIsTrashed: + case PublishStatusType.FailedContentInvalid: + return Request.CreateValidationErrorResponse( + ui.Text("publish", "contentPublishedFailedInvalid", + new[] + { + string.Format("{0} ({1})", publishResult.Result.ContentItem.Name, publishResult.Result.ContentItem.Id), + string.Join(",", publishResult.Result.InvalidProperties.Select(x => x.Alias)) + }, Security.CurrentUser)); + } + } + + //return ok return Request.CreateResponse(HttpStatusCode.OK); }