diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js index 5aa56a80af..2cf7127707 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js @@ -509,6 +509,16 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { 'Failed to check permission for item ' + id); }, + getPermissions: function (nodeIds) { + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetPermissions"), + nodeIds), + 'Failed to get permissions'); + }, + /** * @ngdoc method * @name umbraco.resources.contentResource#save diff --git a/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js index 428b9f4323..e211218ce1 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js @@ -1,288 +1,319 @@ -(function() { - 'use strict'; +(function () { + 'use strict'; - function listViewHelper(localStorageService) { + function listViewHelper(localStorageService) { - var firstSelectedIndex = 0; - var localStorageKey = "umblistViewLayout"; + var firstSelectedIndex = 0; + var localStorageKey = "umblistViewLayout"; - function getLayout(nodeId, availableLayouts) { + function getLayout(nodeId, availableLayouts) { - var storedLayouts = []; + var storedLayouts = []; - if(localStorageService.get(localStorageKey)) { - storedLayouts = localStorageService.get(localStorageKey); - } - - if (storedLayouts && storedLayouts.length > 0) { - for (var i = 0; storedLayouts.length > i; i++) { - var layout = storedLayouts[i]; - if (layout.nodeId === nodeId) { - return setLayout(nodeId, layout, availableLayouts); - } - } - - } - - return getFirstAllowedLayout(availableLayouts); - - } - - function setLayout(nodeId, selectedLayout, availableLayouts) { - - var activeLayout = {}; - var layoutFound = false; - - for (var i = 0; availableLayouts.length > i; i++) { - var layout = availableLayouts[i]; - if (layout.path === selectedLayout.path) { - activeLayout = layout; - layout.active = true; - layoutFound = true; - } else { - layout.active = false; - } - } - - if(!layoutFound) { - activeLayout = getFirstAllowedLayout(availableLayouts); - } - - saveLayoutInLocalStorage(nodeId, activeLayout); - - return activeLayout; - - } - - function saveLayoutInLocalStorage(nodeId, selectedLayout) { - var layoutFound = false; - var storedLayouts = []; - - if(localStorageService.get(localStorageKey)) { - storedLayouts = localStorageService.get(localStorageKey); - } - - if(storedLayouts.length > 0) { - for(var i = 0; storedLayouts.length > i; i++) { - var layout = storedLayouts[i]; - if(layout.nodeId === nodeId) { - layout.path = selectedLayout.path; - layoutFound = true; - } - } - } - - if(!layoutFound) { - var storageObject = { - "nodeId": nodeId, - "path": selectedLayout.path - }; - storedLayouts.push(storageObject); - } - - localStorageService.set(localStorageKey, storedLayouts); - - } - - function getFirstAllowedLayout(layouts) { - - var firstAllowedLayout = {}; - - for (var i = 0; layouts.length > i; i++) { - var layout = layouts[i]; - if (layout.selected === true) { - firstAllowedLayout = layout; - break; + if (localStorageService.get(localStorageKey)) { + storedLayouts = localStorageService.get(localStorageKey); } - } - return firstAllowedLayout; - } + if (storedLayouts && storedLayouts.length > 0) { + for (var i = 0; storedLayouts.length > i; i++) { + var layout = storedLayouts[i]; + if (layout.nodeId === nodeId) { + return setLayout(nodeId, layout, availableLayouts); + } + } - function selectHandler(selectedItem, selectedIndex, items, selection, $event) { + } - var start = 0; - var end = 0; - var item = null; + return getFirstAllowedLayout(availableLayouts); - if ($event.shiftKey === true) { + } - if(selectedIndex > firstSelectedIndex) { + function setLayout(nodeId, selectedLayout, availableLayouts) { - start = firstSelectedIndex; - end = selectedIndex; + var activeLayout = {}; + var layoutFound = false; - for (; end >= start; start++) { - item = items[start]; - selectItem(item, selection); - } + for (var i = 0; availableLayouts.length > i; i++) { + var layout = availableLayouts[i]; + if (layout.path === selectedLayout.path) { + activeLayout = layout; + layout.active = true; + layoutFound = true; + } else { + layout.active = false; + } + } + + if (!layoutFound) { + activeLayout = getFirstAllowedLayout(availableLayouts); + } + + saveLayoutInLocalStorage(nodeId, activeLayout); + + return activeLayout; + + } + + function saveLayoutInLocalStorage(nodeId, selectedLayout) { + var layoutFound = false; + var storedLayouts = []; + + if (localStorageService.get(localStorageKey)) { + storedLayouts = localStorageService.get(localStorageKey); + } + + if (storedLayouts.length > 0) { + for (var i = 0; storedLayouts.length > i; i++) { + var layout = storedLayouts[i]; + if (layout.nodeId === nodeId) { + layout.path = selectedLayout.path; + layoutFound = true; + } + } + } + + if (!layoutFound) { + var storageObject = { + "nodeId": nodeId, + "path": selectedLayout.path + }; + storedLayouts.push(storageObject); + } + + localStorageService.set(localStorageKey, storedLayouts); + + } + + function getFirstAllowedLayout(layouts) { + + var firstAllowedLayout = {}; + + for (var i = 0; layouts.length > i; i++) { + var layout = layouts[i]; + if (layout.selected === true) { + firstAllowedLayout = layout; + break; + } + } + + return firstAllowedLayout; + } + + function selectHandler(selectedItem, selectedIndex, items, selection, $event) { + + var start = 0; + var end = 0; + var item = null; + + if ($event.shiftKey === true) { + + if (selectedIndex > firstSelectedIndex) { + + start = firstSelectedIndex; + end = selectedIndex; + + for (; end >= start; start++) { + item = items[start]; + selectItem(item, selection); + } + + } else { + + start = firstSelectedIndex; + end = selectedIndex; + + for (; end <= start; start--) { + item = items[start]; + selectItem(item, selection); + } + + } } else { - start = firstSelectedIndex; - end = selectedIndex; + if (selectedItem.selected) { + deselectItem(selectedItem, selection); + } else { + selectItem(selectedItem, selection); + } - for (; end <= start; start--) { - item = items[start]; - selectItem(item, selection); - } + firstSelectedIndex = selectedIndex; } - } else { + } - if(selectedItem.selected) { - deselectItem(selectedItem, selection); - } else { - selectItem(selectedItem, selection); + function selectItem(item, selection) { + var isSelected = false; + for (var i = 0; selection.length > i; i++) { + var selectedItem = selection[i]; + if (item.id === selectedItem.id) { + isSelected = true; + } + } + if (!isSelected) { + selection.push({ id: item.id }); + item.selected = true; + } + } + + function deselectItem(item, selection) { + for (var i = 0; selection.length > i; i++) { + var selectedItem = selection[i]; + if (item.id === selectedItem.id) { + selection.splice(i, 1); + item.selected = false; + } + } + } + + function clearSelection(items, folders, selection) { + + var i = 0; + + selection.length = 0; + + if (angular.isArray(items)) { + for (i = 0; items.length > i; i++) { + var item = items[i]; + item.selected = false; + } } - firstSelectedIndex = selectedIndex; - - } - - } - - function selectItem(item, selection) { - var isSelected = false; - for (var i = 0; selection.length > i; i++) { - var selectedItem = selection[i]; - if (item.id === selectedItem.id) { - isSelected = true; + if (angular.isArray(items)) { + for (i = 0; folders.length > i; i++) { + var folder = folders[i]; + folder.selected = false; + } } - } - if(!isSelected) { - selection.push({id: item.id}); - item.selected = true; - } - } + } - function deselectItem(item, selection) { - for (var i = 0; selection.length > i; i++) { - var selectedItem = selection[i]; - if (item.id === selectedItem.id) { - selection.splice(i, 1); - item.selected = false; + function selectAllItems(items, selection, $event) { + + var checkbox = $event.target; + var clearSelection = false; + + if (!angular.isArray(items)) { + return; } - } - } - function clearSelection(items, folders, selection) { + selection.length = 0; - var i = 0; + for (var i = 0; i < items.length; i++) { - selection.length = 0; + var item = items[i]; + + if (checkbox.checked) { + selection.push({ id: item.id }); + } else { + clearSelection = true; + } + + item.selected = checkbox.checked; - if(angular.isArray(items)) { - for(i = 0; items.length > i; i++) { - var item = items[i]; - item.selected = false; } - } - if(angular.isArray(items)) { - for(i = 0; folders.length > i; i++) { - var folder = folders[i]; - folder.selected = false; + if (clearSelection) { + selection.length = 0; } - } - } - function selectAllItems(items, selection, $event) { + } - var checkbox = $event.target; - var clearSelection = false; + function isSelectedAll(items, selection) { - if (!angular.isArray(items)) { - return; - } + var numberOfSelectedItem = 0; - selection.length = 0; + for (var itemIndex = 0; items.length > itemIndex; itemIndex++) { + var item = items[itemIndex]; - for (var i = 0; i < items.length; i++) { + for (var selectedIndex = 0; selection.length > selectedIndex; selectedIndex++) { + var selectedItem = selection[selectedIndex]; - var item = items[i]; + if (item.id === selectedItem.id) { + numberOfSelectedItem++; + } + } - if (checkbox.checked) { - selection.push({id: item.id}); - } else { - clearSelection = true; - } + } - item.selected = checkbox.checked; + if (numberOfSelectedItem === items.length) { + return true; + } - } + } - if (clearSelection) { - selection.length = 0; - } + function setSortingDirection(col, direction, options) { + return options.orderBy.toUpperCase() === col.toUpperCase() && options.orderDirection === direction; + } - } + function setSorting(field, allow, options) { + if (allow) { + options.orderBy = field; - function isSelectedAll(items, selection) { + if (options.orderDirection === "desc") { + options.orderDirection = "asc"; + } else { + options.orderDirection = "desc"; + } + } + } + + //This takes in a dictionary of Ids with Permissions and determines + // the intersect of all permissions to return an object representing the + // listview button permissions + function getButtonPermissions(unmergedPermissions, currentIdsWithPermissions) { + + if (currentIdsWithPermissions == null) { + currentIdsWithPermissions = {}; + } - var numberOfSelectedItem = 0; + //merge the newly retrieved permissions to the main dictionary + _.each(unmergedPermissions, function (value, key, list) { + currentIdsWithPermissions[key] = value; + }); - for(var itemIndex = 0; items.length > itemIndex; itemIndex++) { - var item = items[itemIndex]; + //get the intersect permissions + var arr = []; + _.each(currentIdsWithPermissions, function (value, key, list) { + arr.push(value); + }); - for(var selectedIndex = 0; selection.length > selectedIndex; selectedIndex++) { - var selectedItem = selection[selectedIndex]; + //we need to use 'apply' to call intersection with an array of arrays, + //see: http://stackoverflow.com/a/16229480/694494 + var intersectPermissions = _.intersection.apply(_, arr); - if(item.id === selectedItem.id) { - numberOfSelectedItem++; - } - } + return { + canCopy: _.contains(intersectPermissions, 'O'), //Magic Char = O + canCreate: _.contains(intersectPermissions, 'C'), //Magic Char = C + canDelete: _.contains(intersectPermissions, 'D'), //Magic Char = D + canMove: _.contains(intersectPermissions, 'M'), //Magic Char = M + canPublish: _.contains(intersectPermissions, 'U'), //Magic Char = U + canUnpublish: _.contains(intersectPermissions, 'U'), //Magic Char = Z (however UI says it can't be set, so if we can publish 'U' we can unpublish) + }; + } - } + var service = { + getLayout: getLayout, + getFirstAllowedLayout: getFirstAllowedLayout, + setLayout: setLayout, + saveLayoutInLocalStorage: saveLayoutInLocalStorage, + selectHandler: selectHandler, + selectItem: selectItem, + deselectItem: deselectItem, + clearSelection: clearSelection, + selectAllItems: selectAllItems, + isSelectedAll: isSelectedAll, + setSortingDirection: setSortingDirection, + setSorting: setSorting, + getButtonPermissions: getButtonPermissions + }; - if(numberOfSelectedItem === items.length) { - return true; - } + return service; - } + } - function setSortingDirection(col, direction, options) { - return options.orderBy.toUpperCase() === col.toUpperCase() && options.orderDirection === direction; - } - - - function setSorting(field, allow, options) { - if (allow) { - options.orderBy = field; - - if (options.orderDirection === "desc") { - options.orderDirection = "asc"; - } else { - options.orderDirection = "desc"; - } - } - } - - - - var service = { - getLayout: getLayout, - getFirstAllowedLayout: getFirstAllowedLayout, - setLayout: setLayout, - saveLayoutInLocalStorage: saveLayoutInLocalStorage, - selectHandler: selectHandler, - selectItem: selectItem, - deselectItem: deselectItem, - clearSelection: clearSelection, - selectAllItems: selectAllItems, - isSelectedAll: isSelectedAll, - setSortingDirection: setSortingDirection, - setSorting: setSorting - }; - - return service; - - } - - - angular.module('umbraco.services').factory('listViewHelper', listViewHelper); + angular.module('umbraco.services').factory('listViewHelper', listViewHelper); })(); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js index 554790b6d0..9fbf2947af 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js @@ -21,6 +21,7 @@ function packageHelper(assetsService, treeService, eventsService, $templateCache } angular.module('umbraco.services').factory('packageHelper', packageHelper); +//TODO: I believe this is obsolete function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, mediaHelper, umbRequestHelper) { return { /** sets the image's url, thumbnail and if its a folder */ @@ -319,7 +320,6 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me } }; } - angular.module("umbraco.services").factory("umbPhotoFolderHelper", umbPhotoFolderHelper); /** diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js index 59bc155bf5..aba7fddd1f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js @@ -4,8 +4,8 @@ function booleanEditorController($scope, $rootScope, assetsService) { $scope.renderModel = { value: false }; - - if($scope.model.config.default.toString() === "1" && $scope.model && !$scope.model.value) { + + if ($scope.model.config.default && $scope.model.config.default.toString() === "1" && $scope.model && !$scope.model.value) { $scope.renderModel.value = true; } 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 85e43c02ec..5aade0cac0 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,4 +1,4 @@ -function listViewController($rootScope, $scope, $routeParams, $injector, $cookieStore, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper) { +function listViewController($rootScope, $scope, $routeParams, $injector, $cookieStore, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper, userService) { //this is a quick check to see if we're in create mode, if so just exit - we cannot show children for content // that isn't created yet, if we continue this will use the parent id in the route params which isn't what @@ -58,6 +58,63 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie totalPages: 0, items: [] }; + + //when this is null, we don't check permissions + $scope.buttonPermissions = null; + + //When we are dealing with 'content', we need to deal with permissions on child nodes. + // Currently there is no real good way to + if ($scope.entityType === "content") { + + var idsWithPermissions = null; + + $scope.buttonPermissions = { + canCopy: true, + canCreate: true, + canDelete: true, + canMove: true, + canPublish: true, + canUnpublish: true + }; + + $scope.$watch(function() { + return $scope.selection.length; + }, function(newVal, oldVal) { + + if ((idsWithPermissions == null && newVal > 0) || (idsWithPermissions != null)) { + + //get all of the selected ids + var ids = _.map($scope.selection, function(i) { + return i.id.toString(); + }); + + //remove the dictionary items that don't have matching ids + var filtered = {}; + _.each(idsWithPermissions, function (value, key, list) { + if (_.contains(ids, key)) { + filtered[key] = value; + } + }); + idsWithPermissions = filtered; + + //find all ids that we haven't looked up permissions for + var existingIds = _.keys(idsWithPermissions); + var missingLookup = _.map(_.difference(ids, existingIds), function (i) { + return Number(i); + }); + + if (missingLookup.length > 0) { + contentResource.getPermissions(missingLookup).then(function(p) { + $scope.buttonPermissions = listViewHelper.getButtonPermissions(p, idsWithPermissions); + }); + } + else { + $scope.buttonPermissions = listViewHelper.getButtonPermissions({}, idsWithPermissions); + } + } + }); + + } $scope.options = { displayAtTabNumber: $scope.model.config.displayAtTabNumber ? $scope.model.config.displayAtTabNumber : 1, @@ -166,9 +223,8 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie getListResultsCallback(id, $scope.options).then(function(data) { $scope.actionInProgress = false; - $scope.listViewResultSet = data; - + //update all values for display if ($scope.listViewResultSet.items) { _.each($scope.listViewResultSet.items, function(e, index) { 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 0f8014529e..904939b75f 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 @@ -10,7 +10,7 @@ - +
Create @@ -82,7 +82,7 @@ + /// Returns permissions for all nodes passed in for the current user + /// + /// + /// + [HttpPost] + public Dictionary GetPermissions(int[] nodeIds) + { + return Services.UserService + .GetPermissions(Security.CurrentUser, nodeIds) + .ToDictionary(x => x.EntityId, x => x.AssignedPermissions); + } + [HttpGet] public bool HasPermission(string permissionToCheck, int nodeId) { @@ -352,9 +366,7 @@ namespace Umbraco.Web.Editors return display; } - - /// /// Publishes a document with a given ID /// diff --git a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs index 2c9a6410b4..1f36eb6c5b 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs @@ -292,35 +292,9 @@ namespace Umbraco.Web.Models.Mapping source.HasIdentity ? source.Id : source.ParentId) .FirstOrDefault(); - if (permissions == null) - { - return Enumerable.Empty(); - } - - var result = new List(); - - //can they publish ? - if (permissions.AssignedPermissions.Contains(ActionPublish.Instance.Letter.ToString(CultureInfo.InvariantCulture))) - { - result.Add(ActionPublish.Instance.Letter); - } - //can they send to publish ? - if (permissions.AssignedPermissions.Contains(ActionToPublish.Instance.Letter.ToString(CultureInfo.InvariantCulture))) - { - result.Add(ActionToPublish.Instance.Letter); - } - //can they save ? - if (permissions.AssignedPermissions.Contains(ActionUpdate.Instance.Letter.ToString(CultureInfo.InvariantCulture))) - { - result.Add(ActionUpdate.Instance.Letter); - } - //can they create ? - if (permissions.AssignedPermissions.Contains(ActionNew.Instance.Letter.ToString(CultureInfo.InvariantCulture))) - { - result.Add(ActionNew.Instance.Letter); - } - - return result; + return permissions == null + ? Enumerable.Empty() + : permissions.AssignedPermissions.Where(x => x.Length == 1).Select(x => x.ToUpperInvariant()[0]); } }