From 1e501cc3c375427cc00ad22597b84a7972b50aa6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 3 Oct 2018 11:27:15 +0200 Subject: [PATCH 01/24] wip schedule publish dialog --- .../components/content/edit.controller.js | 24 +++ .../src/less/components/overlays.less | 2 +- .../src/views/components/content/edit.html | 8 + .../content/overlays/schedule.controller.js | 139 ++++++++++++++++++ .../src/views/content/overlays/schedule.html | 85 +++++++++++ .../Umbraco/config/lang/en_us.xml | 1 + 6 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index ed0259f78b..ef7702740a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -536,6 +536,30 @@ }; + $scope.schedule = function() { + clearNotifications($scope.content); + //before we launch the dialog we want to execute all client side validations first + if (formHelper.submitForm({ scope: $scope, action: "schedule" })) { + + var dialog = { + parentScope: $scope, + view: "views/content/overlays/schedule.html", + variants: $scope.content.variants, //set a model property for the dialog + skipFormValidation: true, //when submitting the overlay form, skip any client side validation + submitButtonLabel: "Schedule", + submit: function (model) { + model.submitButtonState = "busy"; + clearNotifications($scope.content); + model.submitButtonState = "success"; + }, + close: function () { + overlayService.close(); + } + }; + overlayService.open(dialog); + } + }; + $scope.preview = function (content) { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/overlays.less b/src/Umbraco.Web.UI.Client/src/less/components/overlays.less index 3fbe32134b..6538a751f9 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/overlays.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/overlays.less @@ -75,7 +75,7 @@ /* ---------- OVERLAY CENTER ---------- */ .umb-overlay.umb-overlay-center { position: absolute; - width: 500px; + width: 600px; height: auto; top: 50%; left: 50%; diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/edit.html b/src/Umbraco.Web.UI.Client/src/views/components/content/edit.html index d5ee000e87..1fb9d6691c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/edit.html @@ -28,6 +28,14 @@ + + + + +
+

+
+ +
+ +
+ +
+ +
+ + + +
+ +
+ +
+
Publish:
+ +
+ + +
+ {{variant.releaseDateFormatted}} +
+ + + Set date + + +
+ + + + +
+ +
Unpublish:
+ +
+ + +
+ {{variant.removeDateFormatted}} +
+ + + Set date + + +
+ + + + +
+ +
+ +
+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index a6ccd30923..28d2f7700d 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -265,6 +265,7 @@ This value is hidden. What languages would you like to publish? What languages would you like to save? + What languages would you like to schedule? What languages would you like to send for approval? Published Languages Unmodified Languages From 739effba467fd0ee7ed3ee85a291f736c798302c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 3 Oct 2018 14:51:20 +0200 Subject: [PATCH 02/24] add schedule publish to the publish combo button --- .../components/content/edit.controller.js | 3 ++- .../services/contenteditinghelper.service.js | 21 +++++++++++++++++-- .../src/views/components/content/edit.html | 8 ------- .../content/overlays/schedule.controller.js | 6 ------ .../src/views/content/overlays/schedule.html | 4 ++-- .../Umbraco/config/lang/en_us.xml | 1 + 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index ef7702740a..73a62b2761 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -177,7 +177,8 @@ methods: { saveAndPublish: $scope.saveAndPublish, sendToPublish: $scope.sendToPublish, - unPublish: $scope.unPublish + unPublish: $scope.unPublish, + schedulePublish: $scope.schedule } }); 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 a11c93c2da..6efdb7ffdc 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 @@ -146,7 +146,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica if (!args.methods) { throw "args.methods is not defined"; } - if (!args.methods.saveAndPublish || !args.methods.sendToPublish || !args.methods.unPublish) { + if (!args.methods.saveAndPublish || !args.methods.sendToPublish || !args.methods.unPublish || !args.methods.schedulePublish) { throw "args.methods does not contain all required defined methods"; } @@ -189,6 +189,16 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica hotKeyWhenHidden: true, alias: "unpublish" }; + case "SCHEDULE": + //schedule publish - schedule doesn't have a permission letter so + // the button letter is made unique so it doesn't collide with anything else + return { + letter: ch, + labelKey: "buttons_schedulePublish", + handler: args.methods.schedulePublish, + alias: "schedulePublish", + addEllipsis: args.content.variants && args.content.variants.length > 1 ? "true" : "false" + }; default: return null; } @@ -199,7 +209,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica //This is the ideal button order but depends on circumstance, we'll use this array to create the button list // Publish, SendToPublish - var buttonOrder = ["U", "H"]; + var buttonOrder = ["U", "H", "SCHEDULE"]; //Create the first button (primary button) //We cannot have the Save or SaveAndPublish buttons if they don't have create permissions when we are creating a new item. @@ -214,6 +224,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica break; } } + //Here's the special check, if the button still isn't set and we are creating and they have create access //we need to add the Save button if (!buttons.defaultButton && args.create && _.contains(args.content.allowedActions, "C")) { @@ -236,6 +247,12 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica } } + // if publishing is allowed also allow schedule publish + // we add this manually becuase it doesn't have a permission so it wont + // get picked up by the loop through permissions + if( _.contains(args.content.allowedActions, "U")) { + buttons.subButtons.push(createButtonDefinition("SCHEDULE")); + } // if we are not creating, then we should add unpublish too, // so long as it's already published and if the user has access to publish diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/edit.html b/src/Umbraco.Web.UI.Client/src/views/components/content/edit.html index 1fb9d6691c..d5ee000e87 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/edit.html @@ -28,14 +28,6 @@ - - - - + @@ -67,7 +67,7 @@ - + diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 28d2f7700d..16b595b9f5 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -131,6 +131,7 @@ Save and schedule Send for approval Save list view + Schedule publish Preview Preview is disabled because there's no template assigned Choose style From fbff56d911a2eaaa242db668508f0a4a6908cbdb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 3 Oct 2018 14:57:45 +0200 Subject: [PATCH 03/24] change schedule flag to save flag --- .../src/views/content/overlays/schedule.controller.js | 2 +- .../src/views/content/overlays/schedule.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 87856c6c53..553aa77106 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 @@ -122,7 +122,7 @@ //when this dialog is closed, reset all 'save' flags $scope.$on('$destroy', function () { for (var i = 0; i < vm.variants.length; i++) { - vm.variants[i].schedule = false; + vm.variants[i].save = false; } }); 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 eb45870425..b5961aaae4 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 @@ -13,7 +13,7 @@ id="{{variant.language.culture}}" name="saveVariantSelector" type="checkbox" - ng-model="variant.schedule" + ng-model="variant.save" ng-change="vm.changeSelection(variant)" style="margin-right: 8px;" />
From 0bbacf46ea3df71b62b7883357f01e71d42baf41 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 3 Oct 2018 16:41:56 +0200 Subject: [PATCH 04/24] add filters --- .../content/overlays/schedule.controller.js | 84 +++++++++++++++++++ .../src/views/content/overlays/schedule.html | 28 +++++-- 2 files changed, 107 insertions(+), 5 deletions(-) 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 553aa77106..fa835341e2 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 @@ -8,6 +8,9 @@ vm.datePickerChange = datePickerChange; vm.clearPublishDate = clearPublishDate; vm.clearUnpublishDate = clearUnpublishDate; + vm.dirtyVariantFilter = dirtyVariantFilter; + vm.pristineVariantFilter = pristineVariantFilter; + vm.changeSelection = changeSelection; vm.currentUser = null; vm.datePickerConfig = { @@ -26,6 +29,7 @@ function onInit() { vm.variants = $scope.model.variants; + vm.hasPristineVariants = false; if(!$scope.model.title) { localizationService.localize("general_scheduledPublishing").then(function(value){ @@ -33,6 +37,40 @@ }); } + _.each(vm.variants, + function (variant) { + variant.compositeId = variant.language.culture + "_" + (variant.segment ? variant.segment : ""); + variant.htmlId = "_content_variant_" + variant.compositeId; + + //check for pristine variants + if (!vm.hasPristineVariants) { + vm.hasPristineVariants = pristineVariantFilter(variant); + } + }); + + if (vm.variants.length !== 0) { + //now sort it so that the current one is at the top + vm.variants = _.sortBy(vm.variants, function (v) { + return v.active ? 0 : 1; + }); + + var active = _.find(vm.variants, function (v) { + return v.active; + }); + + if (active) { + //ensure that the current one is selected + active.schedule = true; + active.save = true; + } + + //$scope.model.disableSubmitButton = !canPublish(); + + } else { + //disable Publish button if we have nothing to publish, should not happen + //$scope.model.disableSubmitButton = true; + } + // get current backoffice user and format dates userService.getCurrentUser().then(function (currentUser) { @@ -117,11 +155,57 @@ } + function changeSelection(variant) { + $scope.model.disableSubmitButton = !canSchedule(); + //need to set the Save state to true if publish is true + variant.save = variant.schedule; + } + + function dirtyVariantFilter(variant) { + //determine a variant is 'dirty' (meaning it will show up as publish-able) if it's + // * the active one + // * it's editor is in a $dirty state + // * it has pending saves + // * it is unpublished + // * it is in NotCreated state + return (variant.active || variant.isDirty || variant.state === "Draft" || variant.state === "PublishedPendingChanges" || variant.state === "NotCreated"); + } + + function pristineVariantFilter(variant) { + return !(dirtyVariantFilter(variant)); + } + + /** Returns true if publishing is possible based on if there are un-published mandatory languages */ + function canSchedule() { + var selected = []; + for (var i = 0; i < vm.variants.length; i++) { + var variant = vm.variants[i]; + + //if this variant will show up in the publish-able list + var publishable = dirtyVariantFilter(variant); + + if ((variant.language.isMandatory && (variant.state === "NotCreated" || variant.state === "Draft")) + && (!publishable || !variant.schedule)) { + //if a mandatory variant isn't published and it's not publishable or not selected to be published + //then we cannot publish anything + + //TODO: Show a message when this occurs + return false; + } + + if (variant.schedule) { + selected.push(variant.schedule); + } + } + return selected.length > 0; + } + onInit(); //when this dialog is closed, reset all 'save' flags $scope.$on('$destroy', function () { for (var i = 0; i < vm.variants.length; i++) { + vm.variants[i].schedule = false; vm.variants[i].save = false; } }); 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 b5961aaae4..b12b697552 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 @@ -6,25 +6,25 @@
-
+
-
- +
+ + -
@@ -81,5 +81,23 @@

+ +
+
+

+
+ +
+
+
+ {{ variant.language.name }} +
+
+ + - +
+
+
+
\ No newline at end of file From 8f9db821593c91dbc1e2a8c114527a826b7c17af Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 4 Oct 2018 14:21:30 +0200 Subject: [PATCH 05/24] clean up states when dialog closes, prevent dialog from closing then date picker is open, wip support for invariant content --- .../overlays/umboverlay.directive.js | 6 + .../components/overlays/umb-overlay.html | 2 +- .../content/overlays/schedule.controller.js | 53 ++-- .../src/views/content/overlays/schedule.html | 242 ++++++++++++------ 4 files changed, 201 insertions(+), 102 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js index 6655bef4ca..07cfbb9848 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js @@ -700,6 +700,12 @@ Opens an overlay to show a custom YSOD.
}; + scope.outSideClick = function() { + if(!scope.model.disableBackdropClick) { + scope.closeOverLay(); + } + }; + unsubscribe.push(unregisterOverlay); scope.$on('$destroy', function () { for (var i = 0; i < unsubscribe.length; i++) { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html b/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html index feacf3adf8..40b0e181bf 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html @@ -1,4 +1,4 @@ -
+
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 fa835341e2..1aad7cf07b 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,17 +1,20 @@ (function () { "use strict"; - function ScheduleContentController($scope, localizationService, dateHelper, userService) { + function ScheduleContentController($scope, $timeout, localizationService, dateHelper, userService) { var vm = this; vm.datePickerChange = datePickerChange; + vm.datePickerShow = datePickerShow; + vm.datePickerClose = datePickerClose; vm.clearPublishDate = clearPublishDate; vm.clearUnpublishDate = clearUnpublishDate; vm.dirtyVariantFilter = dirtyVariantFilter; vm.pristineVariantFilter = pristineVariantFilter; vm.changeSelection = changeSelection; + vm.firstSelectedDates = {}; vm.currentUser = null; vm.datePickerConfig = { pickDate: true, @@ -37,18 +40,21 @@ }); } - _.each(vm.variants, - function (variant) { - variant.compositeId = variant.language.culture + "_" + (variant.segment ? variant.segment : ""); - variant.htmlId = "_content_variant_" + variant.compositeId; + // Check for variants: if a node is invariant it will still have the default language in variants + // so we have to check for length > 1 + if (vm.variants.length > 1) { - //check for pristine variants - if (!vm.hasPristineVariants) { - vm.hasPristineVariants = pristineVariantFilter(variant); - } - }); + _.each(vm.variants, + function (variant) { + variant.compositeId = variant.language.culture + "_" + (variant.segment ? variant.segment : ""); + variant.htmlId = "_content_variant_" + variant.compositeId; + + //check for pristine variants + if (!vm.hasPristineVariants) { + vm.hasPristineVariants = pristineVariantFilter(variant); + } + }); - if (vm.variants.length !== 0) { //now sort it so that the current one is at the top vm.variants = _.sortBy(vm.variants, function (v) { return v.active ? 0 : 1; @@ -64,11 +70,8 @@ active.save = true; } - //$scope.model.disableSubmitButton = !canPublish(); - - } else { - //disable Publish button if we have nothing to publish, should not happen - //$scope.model.disableSubmitButton = true; + $scope.model.disableSubmitButton = !canSchedule(); + } // get current backoffice user and format dates @@ -95,6 +98,16 @@ } } + function datePickerShow() { + $scope.model.disableBackdropClick = true; + } + + function datePickerClose() { + $timeout(function(){ + $scope.model.disableBackdropClick = false; + }); + } + function setPublishDate(variant, date) { if (!date) { @@ -111,6 +124,8 @@ // make sure dates are formatted to the user's locale formatDatesToLocal(variant); + // store the first selected date so we can apply to other selected variants + } function setUnpublishDate(variant, date) { @@ -202,10 +217,14 @@ onInit(); - //when this dialog is closed, reset all 'save' flags + //when this dialog is closed, clean up $scope.$on('$destroy', function () { for (var i = 0; i < vm.variants.length; i++) { vm.variants[i].schedule = false; + vm.variants[i].releaseDate = null; + vm.variants[i].releaseDateFormatted = null; + vm.variants[i].removeDate = null; + vm.variants[i].releaseDateFormatted = null; vm.variants[i].save = false; } }); 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 b12b697552..2547eec32b 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 @@ -1,103 +1,177 @@
-
-

-
+ +
-
+
+

+
-
- -
- -
- - +
-
- - - -
- -
-
Publish:
- -
- - -
- {{variant.releaseDateFormatted}} -
- - - Set date - - -
- - - - -
- -
Unpublish:
- -
- - -
- {{variant.removeDateFormatted}} -
- - - Set date - - -
- - - - -
- -
+
+ +
+ +
+ +
+ {{vm.variants[0].releaseDateFormatted}}
-
- + + Set date + + + + + + + +
+ +
+ +
+ +
+ + +
+ {{vm.variants[0].removeDateFormatted}} +
+ + + Set date + + +
+ + + + +
+
-
+
-
-
-

+ +
+ +
+

-
-
-
- {{ variant.language.name }} -
-
- - - +
+ +
+ +
+ +
+ + + +
+ + - +
+ +
+
Publish:
+ +
+ + +
+ {{variant.releaseDateFormatted}} +
+ + + Set date + + +
+ + + + +
+ +
Unpublish:
+ +
+ + +
+ {{variant.removeDateFormatted}} +
+ + + Set date + + +
+ + + + +
+ +
+ +
+
+ +
+
+
+
+ +
+
+

+
+ +
+
+
+ {{ variant.language.name }} +
+
+ + - +
+
\ No newline at end of file From 1c5547e594f5b42ee132484186f89acf600dab0d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 4 Oct 2018 15:23:38 +0200 Subject: [PATCH 06/24] add better styling for scheduling of invariant content --- .../src/less/properties.less | 37 +++----- .../src/views/content/overlays/schedule.html | 91 ++++++++++--------- 2 files changed, 61 insertions(+), 67 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/properties.less b/src/Umbraco.Web.UI.Client/src/less/properties.less index 06f05ab0aa..2e700dd77a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/properties.less +++ b/src/Umbraco.Web.UI.Client/src/less/properties.less @@ -1,23 +1,21 @@ //----- SCHEDULED PUBLISH ------ -.place-holder { - height: 60px; - width: 60px; - margin: 15px auto; - background-color: @gray-8; -} - .date-wrapper { display: flex; - justify-content: space-around; flex-direction: row; + border-top: 1px solid @gray-10; + border-bottom: 1px solid @gray-10; +} + +.date-wrapper__date { + padding: 10px; } .date-container { text-align: center; } -.date-wrapper__number{ +.date-wrapper__number { font-size: 40px; line-height: 50px; color: @gray-2; @@ -31,21 +29,21 @@ margin-bottom: 5px; } -.date-container__date { - padding: 0 10px; -} .date-container__date:hover { background-color: @gray-10; cursor: pointer; } -.date-wrapper__date{ - font-size: 13px; - color: @gray-6; - margin: 0; +.date-wrapper__date { + padding: 10px; + flex: 1 1 50%; } -.data-wrapper__add{ +.date-wrapper__date:last-of-type { + border-left: 1px solid @gray-10; +} + +.data-wrapper__add { font-size: 18px; line-height: 10px; color: @gray-8; @@ -53,11 +51,6 @@ margin: 0; } -.date-separate { - width: 1px; - background-color: @gray-8; -} - //------------------- HISTORY ------------------ .history { 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 2547eec32b..1a170b9d75 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 @@ -7,62 +7,63 @@

-
+
+
+ + +
+ -
- -
- -
- +
+ {{vm.variants[0].releaseDateFormatted}} +
-
- {{vm.variants[0].releaseDateFormatted}} -
+ + Set date + - - Set date +
+ + + - - - - - - +
-
- -
+
+ -
- +
+ -
- {{vm.variants[0].removeDateFormatted}} -
- - - Set date +
+ {{vm.variants[0].removeDateFormatted}} +
+ +
+ Set date + + +
+ + + - - - - - - +
-
-
From 5b6c6c0cd1462a9954c2e041561487dce0cc390b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 4 Oct 2018 15:37:59 +0200 Subject: [PATCH 07/24] remove schedule publish box from info app --- .../content/umbcontentnodeinfo.directive.js | 111 ------------------ .../content/umb-content-node-info.html | 73 +----------- 2 files changed, 1 insertion(+), 183 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js index 4831ecea8c..2126e80c20 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js @@ -69,9 +69,6 @@ // get document type details scope.documentType = scope.node.documentType; - // make sure dates are formatted to the user's locale - formatDatesToLocal(); - //default setting for redirect url management scope.urlTrackerDisabled = false; @@ -117,22 +114,6 @@ scope.node.template = templateAlias; }; - scope.datePickerChange = function (event, type) { - if (type === 'publish') { - setPublishDate(event.date.format("YYYY-MM-DD HH:mm")); - } else if (type === 'unpublish') { - setUnpublishDate(event.date.format("YYYY-MM-DD HH:mm")); - } - }; - - scope.clearPublishDate = function () { - clearPublishDate(); - }; - - scope.clearUnpublishDate = function () { - clearUnpublishDate(); - }; - function loadAuditTrail() { scope.loadingAuditTrail = true; @@ -243,97 +224,6 @@ } } - function setPublishDate(date) { - - if (!date) { - return; - } - - //The date being passed in here is the user's local date/time that they have selected - //we need to convert this date back to the server date on the model. - - var serverTime = dateHelper.convertToServerStringTime(moment(date), Umbraco.Sys.ServerVariables.application.serverTimeOffset); - - // update publish value - scope.node.releaseDate = serverTime; - - // make sure dates are formatted to the user's locale - formatDatesToLocal(); - - // emit event - var args = { node: scope.node, date: date }; - eventsService.emit("editors.content.changePublishDate", args); - - } - - function clearPublishDate() { - - // update publish value - scope.node.releaseDate = null; - - // emit event - var args = { node: scope.node, date: null }; - eventsService.emit("editors.content.changePublishDate", args); - - } - - function setUnpublishDate(date) { - - if (!date) { - return; - } - - //The date being passed in here is the user's local date/time that they have selected - //we need to convert this date back to the server date on the model. - - var serverTime = dateHelper.convertToServerStringTime(moment(date), Umbraco.Sys.ServerVariables.application.serverTimeOffset); - - // update publish value - scope.node.removeDate = serverTime; - - // make sure dates are formatted to the user's locale - formatDatesToLocal(); - - // emit event - var args = { node: scope.node, date: date }; - eventsService.emit("editors.content.changeUnpublishDate", args); - - } - - function clearUnpublishDate() { - - // update publish value - scope.node.removeDate = null; - - // emit event - var args = { node: scope.node, date: null }; - eventsService.emit("editors.content.changeUnpublishDate", args); - - } - - function ucfirst(string) { - return string.charAt(0).toUpperCase() + string.slice(1); - } - - function formatDatesToLocal() { - // get current backoffice user and format dates - userService.getCurrentUser().then(function (currentUser) { - scope.node.createDateFormatted = dateHelper.getLocalDate(scope.node.createDate, currentUser.locale, 'LLL'); - - scope.node.releaseDateYear = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'YYYY')) : null; - scope.node.releaseDateMonth = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'MMMM')) : null; - scope.node.releaseDateDayNumber = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'DD')) : null; - scope.node.releaseDateDay = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'dddd')) : null; - scope.node.releaseDateTime = scope.node.releaseDate ? ucfirst(dateHelper.getLocalDate(scope.node.releaseDate, currentUser.locale, 'HH:mm')) : null; - - scope.node.removeDateYear = scope.node.removeDate ? ucfirst(dateHelper.getLocalDate(scope.node.removeDate, currentUser.locale, 'YYYY')) : null; - scope.node.removeDateMonth = scope.node.removeDate ? ucfirst(dateHelper.getLocalDate(scope.node.removeDate, currentUser.locale, 'MMMM')) : null; - scope.node.removeDateDayNumber = scope.node.removeDate ? ucfirst(dateHelper.getLocalDate(scope.node.removeDate, currentUser.locale, 'DD')) : null; - scope.node.removeDateDay = scope.node.removeDate ? ucfirst(dateHelper.getLocalDate(scope.node.removeDate, currentUser.locale, 'dddd')) : null; - scope.node.removeDateTime = scope.node.removeDate ? ucfirst(dateHelper.getLocalDate(scope.node.removeDate, currentUser.locale, 'HH:mm')) : null; - }); - } - // load audit trail and redirects when on the info tab evts.push(eventsService.on("app.tabChange", function (event, args) { $timeout(function () { @@ -356,7 +246,6 @@ if(isInfoTab) { loadAuditTrail(); loadRedirectUrls(); - formatDatesToLocal(); setNodePublishStatus(scope.node); } }); diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-content-node-info.html b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-content-node-info.html index c2e5df6f30..03d4318ba2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-content-node-info.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-content-node-info.html @@ -112,78 +112,7 @@
- - - - -
- -
- - - - -
- -
- -
- -
-
{{node.releaseDateMonth}} {{node.releaseDateYear}}
-
{{node.releaseDateDayNumber}}
-
{{node.releaseDateDay}} {{node.releaseDateTime}}
-
- - Set date - -
- -
- - - Clear date - - -
- -
- -
- - -
- -
- -
- -
-
{{node.removeDateMonth}} {{node.removeDateYear}}
-
{{node.removeDateDayNumber}}
-
{{node.removeDateDay}} {{node.removeDateTime}}
-
- - Set date - -
- -
- - - Clear date - -
- -
- - -
-
+ From 99e7fb008e464b1ca55c169afa94cbc59a96a087 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 4 Oct 2018 16:03:13 +0200 Subject: [PATCH 08/24] remove unused styles --- .../src/less/properties.less | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/properties.less b/src/Umbraco.Web.UI.Client/src/less/properties.less index 2e700dd77a..916f1b5a3a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/properties.less +++ b/src/Umbraco.Web.UI.Client/src/less/properties.less @@ -7,33 +7,6 @@ border-bottom: 1px solid @gray-10; } -.date-wrapper__date { - padding: 10px; -} - -.date-container { - text-align: center; -} - -.date-wrapper__number { - font-size: 40px; - line-height: 50px; - color: @gray-2; - font-weight: 900; -} - -.date-container__title { - font-size: 16px; - font-weight: bold; - color: @gray-3; - margin-bottom: 5px; -} - -.date-container__date:hover { - background-color: @gray-10; - cursor: pointer; -} - .date-wrapper__date { padding: 10px; flex: 1 1 50%; @@ -43,14 +16,6 @@ border-left: 1px solid @gray-10; } -.data-wrapper__add { - font-size: 18px; - line-height: 10px; - color: @gray-8; - font-weight: 900; - margin: 0; -} - //------------------- HISTORY ------------------ .history { From 01bb00a8ec32c35520c1ac44e2ce0615f42374f6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 4 Oct 2018 16:04:14 +0200 Subject: [PATCH 09/24] better date formatting --- .../src/views/content/overlays/schedule.controller.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) 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 1aad7cf07b..7974103b7a 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 @@ -99,11 +99,13 @@ } function datePickerShow() { + // prevent the overlay from closing when the date picker is open $scope.model.disableBackdropClick = true; } function datePickerClose() { $timeout(function(){ + // allow the date picker to close now the date picker is closed $scope.model.disableBackdropClick = false; }); } @@ -159,15 +161,12 @@ } function formatDatesToLocal(variant) { - if(variant && variant.releaseDate) { - variant.releaseDateFormatted = dateHelper.getLocalDate(variant.releaseDate, vm.currentUser.locale, "YYYY-MM-DD HH:mm"); + variant.releaseDateFormatted = dateHelper.getLocalDate(variant.releaseDate, vm.currentUser.locale, "MMM Do YYYY, HH:mm"); } - if(variant && variant.removeDate) { - variant.removeDateFormatted = dateHelper.getLocalDate(variant.removeDate, vm.currentUser.locale, "YYYY-MM-DD HH:mm"); + variant.removeDateFormatted = dateHelper.getLocalDate(variant.removeDate, vm.currentUser.locale, "MMM Do YYYY, HH:mm"); } - } function changeSelection(variant) { From 7d56ebf6624c6240c4a85c1f5d54492813295ff5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 4 Oct 2018 20:21:13 +0200 Subject: [PATCH 10/24] fix width of date picker --- src/Umbraco.Web.UI.Client/src/less/main.less | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/less/main.less b/src/Umbraco.Web.UI.Client/src/less/main.less index 6d567c5fb3..0284a79865 100644 --- a/src/Umbraco.Web.UI.Client/src/less/main.less +++ b/src/Umbraco.Web.UI.Client/src/less/main.less @@ -48,6 +48,7 @@ h5.-black { border: none } .bootstrap-datetimepicker-widget { + width: auto !important; td { &.active, span.active { background: @turquoise !important; From a1abe568ce8d83fc4a1584b0782b09cdeb3456cd Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 4 Oct 2018 21:01:47 +0200 Subject: [PATCH 11/24] clean up --- .../content/umbcontentnodeinfo.directive.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js index 2126e80c20..b2e64983d6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js @@ -46,19 +46,6 @@ }); - scope.datePickerConfig = { - pickDate: true, - pickTime: true, - useSeconds: false, - format: "YYYY-MM-DD HH:mm", - icons: { - time: "icon-time", - date: "icon-calendar", - up: "icon-chevron-up", - down: "icon-chevron-down" - } - }; - scope.auditTrailOptions = { "id": scope.node.id }; From 41aa6e680e88079990c786a2fbc0b1c48bd23c99 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 5 Oct 2018 09:54:57 +0200 Subject: [PATCH 12/24] schedule button should always show an ellipsis because it always opens a dialog --- .../src/common/services/contenteditinghelper.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 70deafdeb9..5e9509977b 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 @@ -198,7 +198,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica labelKey: "buttons_schedulePublish", handler: args.methods.schedulePublish, alias: "schedulePublish", - addEllipsis: args.content.variants && args.content.variants.length > 1 ? "true" : "false" + addEllipsis: "true" }; default: return null; From 8eac3c58946e97a6b770f34bec7816887203bd9e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 5 Oct 2018 11:15:21 +0200 Subject: [PATCH 13/24] clean up old schedule publshing button code --- .../components/content/edit.controller.js | 8 ----- .../services/contenteditinghelper.service.js | 34 ------------------- 2 files changed, 42 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index 456673b6b9..71d7da32eb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -97,14 +97,6 @@ eventsService.unsubscribe(evts[e]); } - evts.push(eventsService.on("editors.content.changePublishDate", function (event, args) { - createButtons(args.node); - })); - - evts.push(eventsService.on("editors.content.changeUnpublishDate", function (event, args) { - createButtons(args.node); - })); - evts.push(eventsService.on("editors.documentType.saved", function (name, args) { // if this content item uses the updated doc type we need to reload the content item if (args && args.documentType && args.documentType.key === content.documentType.key) { 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 5e9509977b..777b336447 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 @@ -266,40 +266,6 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica } } - // If we have a scheduled publish or unpublish date change the default button to - // "save" and update the label to "save and schedule - if (args.content.releaseDate || args.content.removeDate) { - - // if save button is alread the default don't change it just update the label - if (buttons.defaultButton && buttons.defaultButton.letter === "A") { - buttons.defaultButton.labelKey = "buttons_saveAndSchedule"; - return buttons; - } - - if (buttons.defaultButton && buttons.subButtons && buttons.subButtons.length > 0) { - // save a copy of the default so we can push it to the sub buttons later - var defaultButtonCopy = angular.copy(buttons.defaultButton); - var newSubButtons = []; - - // if save button is not the default button - find it and make it the default - angular.forEach(buttons.subButtons, function (subButton) { - - if (subButton.letter === "A") { - buttons.defaultButton = subButton; - buttons.defaultButton.labelKey = "buttons_saveAndSchedule"; - } else { - newSubButtons.push(subButton); - } - - }); - - // push old default button into subbuttons - newSubButtons.push(defaultButtonCopy); - buttons.subButtons = newSubButtons; - } - - } - return buttons; }, From 90900067a852d7c8efd08c4243de01356508346f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 7 Oct 2018 15:29:24 +0200 Subject: [PATCH 14/24] wip Add flatpickr library + create flatpickr component --- src/Umbraco.Web.UI.Client/gulpfile.js | 12 +- src/Umbraco.Web.UI.Client/package.json | 1 + .../components/umbflatpickr.directive.js | 164 ++++++++++++++++++ .../content/overlays/schedule.controller.js | 44 +++-- .../src/views/content/overlays/schedule.html | 56 +++--- 5 files changed, 235 insertions(+), 42 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/umbflatpickr.directive.js diff --git a/src/Umbraco.Web.UI.Client/gulpfile.js b/src/Umbraco.Web.UI.Client/gulpfile.js index 2d34e8ecb3..1a2942ec2b 100644 --- a/src/Umbraco.Web.UI.Client/gulpfile.js +++ b/src/Umbraco.Web.UI.Client/gulpfile.js @@ -142,7 +142,7 @@ gulp.task('docserve', function(cb) { **************************/ gulp.task('dependencies', function () { - //bower component specific copy rules + //bower component/npm specific copy rules //this is to patch the sometimes wonky rules these libs are distrbuted under //as we do multiple things in this task, we merge the multiple streams @@ -199,6 +199,16 @@ gulp.task('dependencies', function () { .pipe(gulp.dest(root + targets.lib + "/codemirror")) ); + // npm dependencies + // flatpickr + stream.add( + gulp.src([ + "./node_modules/flatpickr/dist/flatpickr.js", + "./node_modules/flatpickr/dist/flatpickr.css"], + { base: "./node_modules/flatpickr/dist" }) + .pipe(gulp.dest(root + targets.lib + "/flatpickr")) + ); + //copy over libs which are not on bower (/lib) and //libraries that have been managed by bower-installer (/lib-bower) stream.add( diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index c05401a05c..7051c2e3e6 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -5,6 +5,7 @@ "build": "gulp" }, "dependencies": { + "flatpickr": "^4.5.2", "npm": "^6.4.1" }, "devDependencies": { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbflatpickr.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbflatpickr.directive.js new file mode 100644 index 0000000000..828d17e4c5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbflatpickr.directive.js @@ -0,0 +1,164 @@ +(function() { + 'use strict'; + + var umbFlatpickr = { + template: '' + + '' + + '
' + + '
', + controller: umbFlatpickrCtrl, + transclude: true, + bindings: { + ngModel: '<', + options: '<', + onSetup: '&', + onChange: '&?', + onOpen: '&?', + onClose: '&?', + onMonthChange: '&?' + } + }; + + function umbFlatpickrCtrl($element, $timeout, $scope, assetsService) { + var ctrl = this; + var loaded = false; + + ctrl.$onInit = function() { + + // load css file for the date picker + assetsService.loadCss('lib/flatpickr/flatpickr.css', $scope); + + // load the js file for the date picker + assetsService.loadJs('lib/flatpickr/flatpickr.js', $scope).then(function () { + // init date picker + loaded = true; + grabElementAndRunFlatpickr(); + }); + + }; + + ctrl.$onChanges = function() { + if(loaded) { + //grabElementAndRunFlatpickr(); + } + }; + + function grabElementAndRunFlatpickr() { + $timeout(function() { + var transcludeEl = $element.find('ng-transclude')[0]; + var element = transcludeEl.children[0]; + + setDatepicker(element); + }, 0, true); + } + + function setDatepicker(element) { + var fpLib = flatpickr ? flatpickr : FlatpickrInstance; + + if (!fpLib) { + return console.warn('Unable to find any flatpickr installation'); + } + + setUpCallbacks(); + + var fpInstance = new fpLib(element, ctrl.options); + + if (ctrl.onSetup) { + ctrl.onSetup({ + fpItem: fpInstance + }); + } + + // If has ngModel set the date + if (ctrl.ngModel) { + fpInstance.setDate(ctrl.ngModel); + } + + // destroy the flatpickr instance when the dom element is removed + angular.element(element).on('$destroy', function() { + fpInstance.destroy(); + }); + + // Refresh the scope + $scope.$applyAsync(); + } + + function setUpCallbacks() { + // bind hook for onChange + if(ctrl.options && ctrl.onChange) { + ctrl.options.onChange = function(selectedDates, dateStr, instance) { + $timeout(function() { + ctrl.onChange({selectedDates: selectedDates, dateStr: dateStr, instance: instance}); + }); + }; + } + + // bind hook for onOpen + if(ctrl.options && ctrl.onOpen) { + ctrl.options.onOpen = function(selectedDates, dateStr, instance) { + $timeout(function() { + ctrl.onOpen({selectedDates: selectedDates, dateStr: dateStr, instance: instance}); + }); + }; + } + + // bind hook for onOpen + if(ctrl.options && ctrl.onClose) { + ctrl.options.onClose = function(selectedDates, dateStr, instance) { + $timeout(function() { + ctrl.onClose({selectedDates: selectedDates, dateStr: dateStr, instance: instance}); + }); + }; + } + + // bind hook for onMonthChange + if(ctrl.options && ctrl.onMonthChange) { + ctrl.options.onMonthChange = function(selectedDates, dateStr, instance) { + $timeout(function() { + ctrl.onMonthChange({selectedDates: selectedDates, dateStr: dateStr, instance: instance}); + }); + }; + } + + // bind hook for onYearChange + if(ctrl.options && ctrl.onYearChange) { + ctrl.options.onYearChange = function(selectedDates, dateStr, instance) { + $timeout(function() { + ctrl.onYearChange({selectedDates: selectedDates, dateStr: dateStr, instance: instance}); + }); + }; + } + + // bind hook for onReady + if(ctrl.options && ctrl.onReady) { + ctrl.options.onReady = function(selectedDates, dateStr, instance) { + $timeout(function() { + ctrl.onReady({selectedDates: selectedDates, dateStr: dateStr, instance: instance}); + }); + }; + } + + // bind hook for onValueUpdate + if(ctrl.onValueUpdate) { + ctrl.options.onValueUpdate = function(selectedDates, dateStr, instance) { + $timeout(function() { + ctrl.onValueUpdate({selectedDates: selectedDates, dateStr: dateStr, instance: instance}); + }); + }; + } + + // bind hook for onDayCreate + if(ctrl.onDayCreate) { + ctrl.options.onDayCreate = function(selectedDates, dateStr, instance) { + $timeout(function() { + ctrl.onDayCreate({selectedDates: selectedDates, dateStr: dateStr, instance: instance}); + }); + }; + } + + } + } + + angular.module('umbraco.directives').component('umbFlatpickr', umbFlatpickr); + +})(); \ No newline at end of file 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 7974103b7a..6f570be8a5 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 @@ -5,6 +5,7 @@ var vm = this; + vm.datePickerSetup = datePickerSetup; vm.datePickerChange = datePickerChange; vm.datePickerShow = datePickerShow; vm.datePickerClose = datePickerClose; @@ -16,18 +17,6 @@ vm.firstSelectedDates = {}; vm.currentUser = null; - vm.datePickerConfig = { - pickDate: true, - pickTime: true, - useSeconds: false, - format: "YYYY-MM-DD HH:mm", - icons: { - time: "icon-time", - date: "icon-calendar", - up: "icon-chevron-up", - down: "icon-chevron-down" - } - }; function onInit() { @@ -79,8 +68,23 @@ vm.currentUser = currentUser; - // format all dates to local angular.forEach(vm.variants, function(variant) { + + // prevent selecting publish/unpublish date before today + var now = new Date(); + var nowFormatted = moment(now).format("YYYY-MM-DD HH:mm"); + + var datePickerConfig = { + enableTime: true, + dateFormat: "Y-m-d H:i", + time_24hr: true, + minDate: nowFormatted, + defaultDate: nowFormatted + }; + + variant.datePickerConfig = datePickerConfig; + + // format all dates to local if(variant.releaseDate || variant.removeDate) { formatDatesToLocal(variant); } @@ -90,22 +94,24 @@ } - function datePickerChange(variant, event, type) { + function datePickerSetup(variant, datePickerInstance) { + variant.datePickerInstance = datePickerInstance; + }; + + function datePickerChange(variant, dateStr, type) { if (type === 'publish') { - setPublishDate(variant, event.date.format("YYYY-MM-DD HH:mm")); + setPublishDate(variant, dateStr); } else if (type === 'unpublish') { - setUnpublishDate(variant, event.date.format("YYYY-MM-DD HH:mm")); + setUnpublishDate(variant, dateStr); } } function datePickerShow() { - // prevent the overlay from closing when the date picker is open $scope.model.disableBackdropClick = true; } function datePickerClose() { $timeout(function(){ - // allow the date picker to close now the date picker is closed $scope.model.disableBackdropClick = false; }); } @@ -128,6 +134,8 @@ // store the first selected date so we can apply to other selected variants + // variant.datePickerInstance.set("maxDate", moment(variant.releaseDate).format("YYYY-MM-DD HH:mm")); + } function setUnpublishDate(variant, date) { 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 1a170b9d75..665dc003f3 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 @@ -14,25 +14,31 @@
- -
- {{vm.variants[0].releaseDateFormatted}} + + +
+
+ {{vm.variants[0].releaseDateFormatted}} +
+ + + Set date +
- - Set date - - - +
+
@@ -42,25 +48,29 @@
- + on-close="vm.datePickerClose()"> -
- {{vm.variants[0].removeDateFormatted}} +
+
+ {{vm.variants[0].removeDateFormatted}} +
+ + + Set date +
- - - Set date - - + +
From eda87cbbd21624a01b3f5024d55feaba0b62289d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 8 Oct 2018 10:48:57 +0200 Subject: [PATCH 15/24] prevent unpublish date to be before publish date and vice versa --- .../content/overlays/schedule.controller.js | 18 +++++++++++++----- .../src/views/content/overlays/schedule.html | 3 ++- 2 files changed, 15 insertions(+), 6 deletions(-) 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 6f570be8a5..9b84bd5335 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 @@ -94,8 +94,14 @@ } - function datePickerSetup(variant, datePickerInstance) { - variant.datePickerInstance = datePickerInstance; + function datePickerSetup(variant, type, datePickerInstance) { + // store a date picker instance for publish and unpublish picker + // so we can change the settings independently. + if (type === 'publish') { + variant.releaseDatePickerInstance = datePickerInstance; + } else if (type === 'unpublish') { + variant.removeDatePickerInstance = datePickerInstance; + } }; function datePickerChange(variant, dateStr, type) { @@ -132,9 +138,8 @@ // make sure dates are formatted to the user's locale formatDatesToLocal(variant); - // store the first selected date so we can apply to other selected variants - - // variant.datePickerInstance.set("maxDate", moment(variant.releaseDate).format("YYYY-MM-DD HH:mm")); + // make sure the unpublish date can't be before the publish date + variant.removeDatePickerInstance.set("minDate", moment(variant.releaseDate).format("YYYY-MM-DD HH:mm")); } @@ -154,6 +159,9 @@ // make sure dates are formatted to the user's locale formatDatesToLocal(variant); + // make sure the publish date can't be after the publish date + variant.releaseDatePickerInstance.set("maxDate", moment(variant.removeDate).format("YYYY-MM-DD HH:mm")); + } function clearPublishDate(variant) { 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 665dc003f3..f6b374a95f 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 @@ -18,7 +18,7 @@ @@ -51,6 +51,7 @@ From 8c71aefe707d124b3dd337c212e68d297c8dfc04 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 8 Oct 2018 13:58:38 +0200 Subject: [PATCH 16/24] prevents overlay from closing when clicking inside date picker --- .../common/directives/components/events/events.directive.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/events.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/events.directive.js index 3a467807a3..21980be925 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/events.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/events.directive.js @@ -173,6 +173,12 @@ angular.module('umbraco.directives') return; } + // ignore clicks in flatpickr datepicker + var flatpickr = $(event.target).closest(".flatpickr-calendar"); + if (flatpickr.length === 1) { + return; + } + //ignore clicks inside this element if( $(element).has( $(event.target) ).length > 0 ){ return; From fb783e33afb996fb4bf6c2c7e105d53adf71a136 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 8 Oct 2018 13:59:25 +0200 Subject: [PATCH 17/24] add flatpickr to variants --- .../src/views/content/overlays/schedule.html | 72 ++++++++++--------- 1 file changed, 37 insertions(+), 35 deletions(-) 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 f6b374a95f..65db34d077 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 @@ -24,9 +24,9 @@ on-close="vm.datePickerClose()">
-
+
+ Set date @@ -53,13 +53,13 @@ options="vm.variants[0].datePickerConfig" on-setup="vm.datePickerSetup(vm.variants[0], 'unpublish', fpItem)" on-change="vm.datePickerChange(vm.variants[0], dateStr, 'unpublish')" - on-show="vm.datePickerShow()" + on-open="vm.datePickerShow()" on-close="vm.datePickerClose()">
-
+
+
Set date @@ -111,22 +111,23 @@
Publish:
- - -
- {{variant.releaseDateFormatted}} + + - - - Set date - - - - + @@ -135,22 +136,23 @@
Unpublish:
- - -
- {{variant.removeDateFormatted}} + +
+ + + + Set date +
- - - Set date - - - - +
From 6869833c5475f11ac5f3c472e914e865c46d7fa7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 8 Oct 2018 14:41:14 +0200 Subject: [PATCH 18/24] clean up settings when dates are cleared --- .../src/views/content/overlays/schedule.controller.js | 6 ++++++ 1 file changed, 6 insertions(+) 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 9b84bd5335..06c0258472 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 @@ -167,12 +167,18 @@ function clearPublishDate(variant) { if(variant && variant.releaseDate) { variant.releaseDate = null; + // we don't have a publish date anymore so we can clear the min date for unpublish + var now = new Date(); + var nowFormatted = moment(now).format("YYYY-MM-DD HH:mm"); + variant.removeDatePickerInstance.set("minDate", nowFormatted); } } function clearUnpublishDate(variant) { if(variant && variant.removeDate) { variant.removeDate = null; + // we don't have a unpublish date anymore so we can clear the max date for publish + variant.releaseDatePickerInstance.set("maxDate", null); } } From 3d345badc3a1798e73d195a789387732a4991b55 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 8 Oct 2018 15:22:15 +0200 Subject: [PATCH 19/24] add comments to schedule controller + fix problem with backdrop clicks --- .../content/overlays/schedule.controller.js | 86 +++++++++++++++++-- .../src/views/content/overlays/schedule.html | 16 ++-- 2 files changed, 88 insertions(+), 14 deletions(-) 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 06c0258472..bb4aa3ca48 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 @@ -94,6 +94,12 @@ } + /** + * Callback when date is set up + * @param {any} variant + * @param {any} type publish or unpublish + * @param {any} datePickerInstance The date picker instance + */ function datePickerSetup(variant, type, datePickerInstance) { // store a date picker instance for publish and unpublish picker // so we can change the settings independently. @@ -104,6 +110,12 @@ } }; + /** + * Callback when date picker date changes + * @param {any} variant + * @param {any} dateStr Date string from the date picker + * @param {any} type publish or unpublish + */ function datePickerChange(variant, dateStr, type) { if (type === 'publish') { setPublishDate(variant, dateStr); @@ -112,16 +124,57 @@ } } - function datePickerShow() { - $scope.model.disableBackdropClick = true; + /** + * Add flag when a date picker opens is we can prevent the overlay from closing + * @param {any} variant + * @param {any} type publish or unpublish + */ + function datePickerShow(variant, type) { + if (type === 'publish') { + variant.releaseDatePickerOpen = true; + } else if (type === 'unpublish') { + variant.removeDatePickerOpen = true; + } + checkForBackdropClick(); } - function datePickerClose() { + /** + * Remove flag when a date picker closes so the overlay can be closed again + * @param {any} variant + * @param {any} type publish or unpublish + */ + function datePickerClose(variant, type) { $timeout(function(){ - $scope.model.disableBackdropClick = false; - }); + if (type === 'publish') { + variant.releaseDatePickerOpen = false; + } else if (type === 'unpublish') { + variant.removeDatePickerOpen = false; + } + checkForBackdropClick(); + }, 200); } + /** + * Prevent the overlay from closing if any date pickers are open + */ + function checkForBackdropClick() { + + var open = _.find(vm.variants, function (variant) { + return variant.releaseDatePickerOpen || variant.removeDatePickerOpen; + }); + + if(open) { + $scope.model.disableBackdropClick = true; + } else { + $scope.model.disableBackdropClick = false; + } + } + + /** + * Sets the selected publish date + * @param {any} variant + * @param {any} date The selected date + */ function setPublishDate(variant, date) { if (!date) { @@ -143,6 +196,11 @@ } + /** + * Sets the selected unpublish date + * @param {any} variant + * @param {any} date The selected date + */ function setUnpublishDate(variant, date) { if (!date) { @@ -164,6 +222,10 @@ } + /** + * Clears the publish date + * @param {any} variant + */ function clearPublishDate(variant) { if(variant && variant.releaseDate) { variant.releaseDate = null; @@ -174,6 +236,10 @@ } } + /** + * Clears the unpublish date + * @param {any} variant + */ function clearUnpublishDate(variant) { if(variant && variant.removeDate) { variant.removeDate = null; @@ -182,6 +248,10 @@ } } + /** + * Formates the selected dates to fit the user culture + * @param {any} variant + */ function formatDatesToLocal(variant) { if(variant && variant.releaseDate) { variant.releaseDateFormatted = dateHelper.getLocalDate(variant.releaseDate, vm.currentUser.locale, "MMM Do YYYY, HH:mm"); @@ -190,7 +260,11 @@ variant.removeDateFormatted = dateHelper.getLocalDate(variant.removeDate, vm.currentUser.locale, "MMM Do YYYY, HH:mm"); } } - + + /** + * Called when new variants are selected or deselected + * @param {any} variant + */ function changeSelection(variant) { $scope.model.disableSubmitButton = !canSchedule(); //need to set the Save state to true if publish is true 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 65db34d077..0486bf68dd 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 @@ -20,8 +20,8 @@ options="vm.variants[0].datePickerConfig" on-setup="vm.datePickerSetup(vm.variants[0], 'publish', fpItem)" on-change="vm.datePickerChange(vm.variants[0], dateStr, 'publish')" - on-open="vm.datePickerShow()" - on-close="vm.datePickerClose()"> + on-open="vm.datePickerShow(vm.variants[0], 'publish')" + on-close="vm.datePickerClose(vm.variants[0], 'publish')">