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 f4c6063a9a..e7ecb5c93c 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 @@ -506,6 +506,37 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt }, + /** + * @ngdoc method + * @name umbraco.services.contentEditingHelper#getPermissionsForContent + * @methodOf umbraco.services.contentEditingHelper + * @function + * + * @description + * Returns a object with permissions for user. + */ + getPermissionsForContent: function () { + + // Just ensure we do have an editorState + if (!editorState.current) return null; + + // Fetch current node allowed actions for the current user + // This is the current node & not each individual child node in the list + const currentUserPermissions = editorState.current.allowedActions || []; + + // Create a nicer model rather than the funky & hard to remember permissions strings + const currentNodePermissions = { + canCopy: currentUserPermissions.includes('O'), //Magic Char = O + canCreate: currentUserPermissions.includes('C'), //Magic Char = C + canDelete: currentUserPermissions.includes('D'), //Magic Char = D + canMove: currentUserPermissions.includes('M'), //Magic Char = M + canPublish: currentUserPermissions.includes('U'), //Magic Char = U + canUnpublish: currentUserPermissions.includes('Z') //Magic Char = Z + }; + + return currentNodePermissions; + }, + /** * @ngdoc method * @name umbraco.services.contentEditingHelper#reBindChangedProperties diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less index b8084bc435..bee757a90d 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less @@ -1,3 +1,11 @@ +umb-date-time-picker { + &.--disabled { + cursor: not-allowed; + pointer-events: none; + user-select: none; + } +} + .flatpickr-calendar { border-radius: @baseBorderRadius; box-shadow: 0 5px 10px 0 rgba(0,0,0,0.16); diff --git a/src/Umbraco.Web.UI.Client/src/less/properties.less b/src/Umbraco.Web.UI.Client/src/less/properties.less index 7960aae2c9..101faab724 100644 --- a/src/Umbraco.Web.UI.Client/src/less/properties.less +++ b/src/Umbraco.Web.UI.Client/src/less/properties.less @@ -47,16 +47,17 @@ flex-direction: row; } -.date-wrapper-mini--checkbox{ +.date-wrapper-mini--checkbox { margin: 0 0 0 28px; } .date-wrapper-mini__date { display: flex; - + flex-direction: column; margin-left: 5px; margin-top: 5px; margin-bottom: 10px; + flex: 1 1 50%; &:first-of-type { margin-left: 0; @@ -67,8 +68,8 @@ } } -.date-wrapper-mini__date .flatpickr-input > a { - +.date-wrapper-mini__date .flatpickr-input > a, +.date-wrapper-mini__date .flatpickr-input > button { display: flex; align-items: center; justify-content: center; diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.rights.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.rights.controller.js index 96c2ef0a80..727872c903 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.rights.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.rights.controller.js @@ -23,12 +23,11 @@ function onInit() { vm.loading = true; - contentResource.getDetailedPermissions($scope.currentNode.id).then(function (userGroups) { + contentResource.getDetailedPermissions($scope.currentNode.id).then(userGroups => { initData(userGroups); vm.loading = false; currentForm = angularHelper.getCurrentForm($scope); }); - } /** @@ -72,7 +71,7 @@ //if no permissions are explicitly set this means we need to show the defaults vm.selectedUserGroup.permissions = vm.selectedUserGroup.defaultPermissions; } - localizationService.localize("defaultdialogs_permissionsSetForGroup", [$scope.currentNode.name, vm.selectedUserGroup.name]).then(function (value) { + localizationService.localize("defaultdialogs_permissionsSetForGroup", [$scope.currentNode.name, vm.selectedUserGroup.name]).then(value => { vm.labels.permissionsSetForGroup = value; }); setViewSate("managePermissions"); @@ -160,7 +159,7 @@ permissions: permissionsSave }; - contentResource.savePermissions(saveModel).then(function (userGroups) { + contentResource.savePermissions(saveModel).then(userGroups => { //re-assign model from server since it could have changed initData(userGroups); @@ -168,10 +167,11 @@ // clear dirty state on the form so we don't see the discard changes notification // we use a timeout here because in some cases the initData reformats the userGroups model and triggers a change after the form state was changed $timeout(function() { - if(currentForm) { - currentForm.$dirty = false; + if (currentForm) { + currentForm.$dirty = false; } }); + $scope.dialog.confirmDiscardChanges = false; vm.saveState = "success"; vm.saveSuccces = true; @@ -185,28 +185,33 @@ function closeDialog() { // check if form has been changed. If it has show discard changes notification if (currentForm && currentForm.$dirty) { - localizationService.localizeMany(["prompt_unsavedChanges", "prompt_unsavedChangesWarning", "prompt_discardChanges", "prompt_stay"]).then( - function(values) { - var overlay = { - "view": "default", - "title": values[0], - "content": values[1], - "disableBackdropClick": true, - "disableEscKey": true, - "submitButtonLabel": values[2], - "closeButtonLabel": values[3], - submit: function () { - overlayService.close(); - navigationService.hideDialog(); - }, - close: function () { - overlayService.close(); - } - }; - overlayService.open(overlay); - } - ); + const labelKeys = [ + "prompt_unsavedChanges", + "prompt_unsavedChangesWarning", + "prompt_discardChanges", + "prompt_stay" + ]; + + localizationService.localizeMany(labelKeys).then(values => { + + const overlay = { + view: "default", + title: values[0], + content: values[1], + disableBackdropClick: true, + disableEscKey: true, + submitButtonLabel: values[2], + closeButtonLabel: values[3], + submit: () => { + overlayService.close(); + navigationService.hideDialog(); + }, + close: () => overlayService.close() + }; + + overlayService.open(overlay); + }); } else { navigationService.hideDialog(); } diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.controller.js index a69de224dd..18121bb2d3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function ScheduleContentController($scope, $timeout, localizationService, dateHelper, userService, contentEditingHelper) { + function ScheduleContentController($scope, $timeout, editorState, localizationService, dateHelper, userService, contentEditingHelper) { var vm = this; @@ -21,11 +21,15 @@ var origDates = []; function onInit() { + + //when this is null, we don't check permissions + vm.currentNodePermissions = contentEditingHelper.getPermissionsForContent(); + vm.canUnpublish = vm.currentNodePermissions ? vm.currentNodePermissions.canUnpublish : true; vm.variants = $scope.model.variants; vm.displayVariants = vm.variants.slice(0);// shallow copy, we dont want to share the array-object(because we will be performing a sort method) but each entry should be shared (because we need validation and notifications). - if(!$scope.model.title) { + if (!$scope.model.title) { localizationService.localize("general_scheduledPublishing").then(value => { $scope.model.title = value; }); @@ -65,18 +69,25 @@ var now = new Date(); var nowFormatted = moment(now).format("YYYY-MM-DD HH:mm"); - var datePickerConfig = { + const datePickerPublishConfig = { enableTime: true, dateFormat: "Y-m-d H:i", time_24hr: true, minDate: nowFormatted, - defaultDate: nowFormatted + defaultDate: nowFormatted, + clickOpens: true }; + + const datePickerUnpublishConfig = Utilities.extend({}, datePickerPublishConfig, { + clickOpens: vm.canUnpublish + }); - variant.datePickerConfig = datePickerConfig; + + variant.datePickerPublishConfig = datePickerPublishConfig; + variant.datePickerUnpublishConfig = datePickerUnpublishConfig; // format all dates to local - if(variant.releaseDate || variant.expireDate) { + if (variant.releaseDate || variant.expireDate) { formatDatesToLocal(variant); } }); @@ -348,7 +359,8 @@ // remove properties only needed for this dialog delete variant.releaseDateFormatted; delete variant.expireDateFormatted; - delete variant.datePickerConfig; + delete variant.datePickerPublishConfig; + delete variant.datePickerUnpublishConfig; delete variant.releaseDatePickerInstance; delete variant.expireDatePickerInstance; delete variant.releaseDatePickerOpen; diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html index f383fb200a..8fca0973e4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html @@ -15,15 +15,19 @@
- +
- @@ -34,7 +38,11 @@ - @@ -47,27 +55,41 @@ Unpublish at -
- +
+
- -
- @@ -119,14 +141,18 @@
Publish:  {{variant.releaseDateFormatted}}
- +
- @@ -135,7 +161,11 @@
-
@@ -144,15 +174,20 @@
Unpublish:  {{variant.expireDateFormatted}}
-
- +
+
- @@ -161,7 +196,11 @@
-
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 c3c5dff69b..d6c6cbd451 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($scope, $interpolate, $routeParams, $injector, $timeout, currentUserResource, notificationsService, iconHelper, editorState, localizationService, appState, $location, listViewHelper, navigationService, editorService, overlayService, languageResource, mediaHelper, eventsService) { +function listViewController($scope, $interpolate, $routeParams, $injector, $timeout, currentUserResource, notificationsService, iconHelper, editorState, localizationService, appState, $location, contentEditingHelper, listViewHelper, navigationService, editorService, overlayService, languageResource, mediaHelper, eventsService) { //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 @@ -67,28 +67,8 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time $scope.createAllowedButtonSingleWithBlueprints = false; $scope.createAllowedButtonMultiWithBlueprints = false; - //when this is null, we don't check permissions - $scope.currentNodePermissions = null; - - if ($scope.entityType === "content") { - //Just ensure we do have an editorState - if (editorState.current) { - //Fetch current node allowed actions for the current user - //This is the current node & not each individual child node in the list - var currentUserPermissions = editorState.current.allowedActions; - - //Create a nicer model rather than the funky & hard to remember permissions strings - $scope.currentNodePermissions = { - "canCopy": _.contains(currentUserPermissions, 'O'), //Magic Char = O - "canCreate": _.contains(currentUserPermissions, 'C'), //Magic Char = C - "canDelete": _.contains(currentUserPermissions, 'D'), //Magic Char = D - "canMove": _.contains(currentUserPermissions, 'M'), //Magic Char = M - "canPublish": _.contains(currentUserPermissions, 'U'), //Magic Char = U - "canUnpublish": _.contains(currentUserPermissions, 'U') //Magic Char = Z (however UI says it can't be set, so if we can publish 'U' we can unpublish) - }; - } - } + $scope.currentNodePermissions = $scope.entityType === "content" ? contentEditingHelper.getPermissionsForContent() : null; //when this is null, we don't check permissions $scope.buttonPermissions = null;