true or false to toggle the switch.
+@param {string} inputId Set the id of the toggle.
@param {callback} onClick The function which should be called when the toggle is clicked.
@param {string=} showLabels Set to true or false to show a "On" or "Off" label next to the switch.
@param {string=} labelOn Set a custom label for when the switched is turned on. It will default to "On".
@@ -122,6 +123,7 @@
scope: {
checked: "=",
disabled: "=",
+ inputId: "@",
onClick: "&",
labelOn: "@?",
labelOff: "@?",
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 552e95563f..2a2852c24f 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
@@ -766,16 +766,6 @@
clearNotifications($scope.content);
//before we launch the dialog we want to execute all client side validations first
if (formHelper.submitForm({ scope: $scope, action: "schedule" })) {
-
- //used to track the original values so if the user doesn't save the schedule and they close the dialog we reset the dates back to what they were.
- let origDates = [];
- for (let i = 0; i < $scope.content.variants.length; i++) {
- origDates.push({
- releaseDate: $scope.content.variants[i].releaseDate,
- expireDate: $scope.content.variants[i].expireDate
- });
- }
-
if (!isContentCultureVariant()) {
//ensure the flags are set
$scope.content.variants[0].save = true;
@@ -784,10 +774,17 @@
var dialog = {
parentScope: $scope,
view: "views/content/overlays/schedule.html",
- variants: $scope.content.variants, //set a model property for the dialog
+ variants: angular.copy($scope.content.variants), //set a model property for the dialog
skipFormValidation: true, //when submitting the overlay form, skip any client side validation
submitButtonLabelKey: "buttons_schedulePublish",
submit: function (model) {
+ for (let i = 0; i < $scope.content.variants.length; i++) {
+ $scope.content.variants[i].releaseDate = model.variants[i].releaseDate;
+ $scope.content.variants[i].expireDate = model.variants[i].expireDate;
+ $scope.content.variants[i].releaseDateFormatted = model.variants[i].releaseDateFormatted;
+ $scope.content.variants[i].expireDateFormatted = model.variants[i].expireDateFormatted;
+ }
+
model.submitButtonState = "busy";
clearNotifications($scope.content);
@@ -810,7 +807,7 @@
}
model.submitButtonState = "error";
//re-map the dialog model since we've re-bound the properties
- dialog.variants = $scope.content.variants;
+ dialog.variants = angular.copy($scope.content.variants);
//don't reject, we've handled the error
return $q.when(err);
});
@@ -818,11 +815,6 @@
},
close: function () {
overlayService.close();
- //restore the dates
- for (let i = 0; i < $scope.content.variants.length; i++) {
- $scope.content.variants[i].releaseDate = origDates[i].releaseDate;
- $scope.content.variants[i].expireDate = origDates[i].expireDate;
- }
}
};
overlayService.open(dialog);
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 a289f8c225..78a2111fc5 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
@@ -307,6 +307,8 @@
// get current backoffice user and format dates
userService.getCurrentUser().then(function (currentUser) {
scope.currentVariant.createDateFormatted = dateHelper.getLocalDate(scope.currentVariant.createDate, currentUser.locale, 'LLL');
+ scope.currentVariant.releaseDateFormatted = dateHelper.getLocalDate(scope.currentVariant.releaseDate, currentUser.locale, 'LLL');
+ scope.currentVariant.expireDateFormatted = dateHelper.getLocalDate(scope.currentVariant.expireDate, currentUser.locale, 'LLL');
});
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/deepBlur.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/deepBlur.directive.js
new file mode 100644
index 0000000000..fdff6459c8
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/deepBlur.directive.js
@@ -0,0 +1,45 @@
+ // A slightly modified version of https://github.com/myplanet/angular-deep-blur/blob/master/angular-deep-blur.js - Kudos to Ufuk Kayserilioglu (paracycle)
+ (function () {
+ 'use strict';
+
+ function DeepBlurDirective($timeout){
+
+ function controller($scope, $element, $attrs) {
+ var leaveExpr = $attrs.deepBlur,
+ dom = $element[0];
+
+ function containsDom(parent, dom) {
+ while (dom) {
+ if (dom === parent) {
+ return true;
+ }
+ dom = dom.parentNode;
+ }
+ return false;
+ }
+
+ function onBlur(e) {
+ var targetElement = e.relatedTarget;
+
+ if (!containsDom(dom, targetElement)) {
+ $timeout(function () {
+ $scope.$apply(leaveExpr);
+ }, 10);
+ }
+ }
+
+ dom.addEventListener('blur', onBlur, true);
+ }
+
+ var directive = {
+ restrict: 'A',
+ controller: controller
+ };
+
+ return directive;
+
+ }
+
+ angular.module('umbraco.directives').directive('deepBlur', DeepBlurDirective);
+
+ })();
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
deleted file mode 100644
index 53aa7475c4..0000000000
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/events.directive.js
+++ /dev/null
@@ -1,273 +0,0 @@
-/**
-* @description Utillity directives for key and field events
-**/
-angular.module('umbraco.directives')
-
- .directive('onDragEnter', function () {
- return {
- link: function (scope, elm, attrs) {
- var f = function () {
- scope.$apply(attrs.onDragEnter);
- };
- elm.on("dragenter", f);
- scope.$on("$destroy", function () { elm.off("dragenter", f); });
- }
- };
- })
-
- .directive('onDragLeave', function () {
- return function (scope, elm, attrs) {
- var f = function (event) {
- var rect = this.getBoundingClientRect();
- var getXY = function getCursorPosition(event) {
- var x, y;
-
- if (typeof event.clientX === 'undefined') {
- // try touch screen
- x = event.pageX + document.documentElement.scrollLeft;
- y = event.pageY + document.documentElement.scrollTop;
- } else {
- x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
- y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
- }
-
- return { x: x, y: y };
- };
-
- var e = getXY(event.originalEvent);
-
- // Check the mouseEvent coordinates are outside of the rectangle
- if (e.x > rect.left + rect.width - 1 || e.x < rect.left || e.y > rect.top + rect.height - 1 || e.y < rect.top) {
- scope.$apply(attrs.onDragLeave);
- }
- };
-
- elm.on("dragleave", f);
- scope.$on("$destroy", function () { elm.off("dragleave", f); });
- };
- })
-
- .directive('onDragOver', function () {
- return {
- link: function (scope, elm, attrs) {
- var f = function () {
- scope.$apply(attrs.onDragOver);
- };
- elm.on("dragover", f);
- scope.$on("$destroy", function () { elm.off("dragover", f); });
- }
- };
- })
-
- .directive('onDragStart', function () {
- return {
- link: function (scope, elm, attrs) {
- var f = function () {
- scope.$apply(attrs.onDragStart);
- };
- elm.on("dragstart", f);
- scope.$on("$destroy", function () { elm.off("dragstart", f); });
- }
- };
- })
-
- .directive('onDragEnd', function () {
- return {
- link: function (scope, elm, attrs) {
- var f = function () {
- scope.$apply(attrs.onDragEnd);
- };
- elm.on("dragend", f);
- scope.$on("$destroy", function () { elm.off("dragend", f); });
- }
- };
- })
-
- .directive('onDrop', function () {
- return {
- link: function (scope, elm, attrs) {
- var f = function () {
- scope.$apply(attrs.onDrop);
- };
- elm.on("drop", f);
- scope.$on("$destroy", function () { elm.off("drop", f); });
- }
- };
- })
-
- .directive('onOutsideClick', function ($timeout, angularHelper) {
- return function (scope, element, attrs) {
-
- var eventBindings = [];
-
- function oneTimeClick(event) {
- var el = event.target.nodeName;
-
- //ignore link and button clicks
- var els = ["INPUT", "A", "BUTTON"];
- if (els.indexOf(el) >= 0) { return; }
-
- // ignore clicks on new overlay
- var parents = $(event.target).parents("a,button,.umb-overlay,.umb-tour");
- if (parents.length > 0) {
- return;
- }
-
- // ignore clicks on dialog from old dialog service
- var oldDialog = $(event.target).parents("#old-dialog-service");
- if (oldDialog.length === 1) {
- return;
- }
-
- // ignore clicks in tinyMCE dropdown(floatpanel)
- var floatpanel = $(event.target).closest(".mce-floatpanel");
- if (floatpanel.length === 1) {
- 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;
- }
-
- // please to not use angularHelper.safeApply here, it won't work
- scope.$apply(attrs.onOutsideClick);
- }
-
-
- $timeout(function () {
-
- if ("bindClickOn" in attrs) {
-
- eventBindings.push(scope.$watch(function () {
- return attrs.bindClickOn;
- }, function (newValue) {
- if (newValue === "true") {
- $(document).on("click", oneTimeClick);
- } else {
- $(document).off("click", oneTimeClick);
- }
- }));
-
- } else {
- $(document).on("click", oneTimeClick);
- }
-
- scope.$on("$destroy", function () {
- $(document).off("click", oneTimeClick);
-
- // unbind watchers
- for (var e in eventBindings) {
- eventBindings[e]();
- }
-
- });
- }); // Temp removal of 1 sec timeout to prevent bug where overlay does not open. We need to find a better solution.
-
- };
- })
-
- .directive('onRightClick', function ($parse) {
-
- document.oncontextmenu = function (e) {
- if (e.target.hasAttribute('on-right-click')) {
- e.preventDefault();
- e.stopPropagation();
- return false;
- }
- };
-
- return function (scope, el, attrs) {
- el.on('contextmenu', function (e) {
- e.preventDefault();
- e.stopPropagation();
- var fn = $parse(attrs.onRightClick);
- scope.$apply(function () {
- fn(scope, { $event: e });
- });
- return false;
- });
- };
- })
-
- .directive('onDelayedMouseleave', function ($timeout, $parse) {
- return {
-
- restrict: 'A',
-
- link: function (scope, element, attrs, ctrl) {
- var active = false;
- var fn = $parse(attrs.onDelayedMouseleave);
-
- var leave_f = function (event) {
- var callback = function () {
- fn(scope, { $event: event });
- };
-
- active = false;
- $timeout(function () {
- if (active === false) {
- scope.$apply(callback);
- }
- }, 650);
- };
-
- var enter_f = function (event, args) {
- active = true;
- };
-
-
- element.on("mouseleave", leave_f);
- element.on("mouseenter", enter_f);
-
- //unsub events
- scope.$on("$destroy", function () {
- element.off("mouseleave", leave_f);
- element.off("mouseenter", enter_f);
- });
- }
- };
- })
-
- // A slightly modified version of https://github.com/myplanet/angular-deep-blur/blob/master/angular-deep-blur.js - Kudos to Ufuk Kayserilioglu (paracycle)
- .directive('deepBlur', function ($timeout) {
- return {
-
- restrict: 'A',
-
- controller: function ($scope, $element, $attrs) {
- var leaveExpr = $attrs.deepBlur,
- dom = $element[0];
-
- function containsDom(parent, dom) {
- while (dom) {
- if (dom === parent) {
- return true;
- }
- dom = dom.parentNode;
- }
- return false;
- }
-
- function onBlur(e) {
- var targetElement = e.relatedTarget;
-
- if (!containsDom(dom, targetElement)) {
- $timeout(function () {
- $scope.$apply(leaveExpr);
- }, 10);
- }
- }
-
- dom.addEventListener('blur', onBlur, true);
- }
- };
- });
-
-
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDelayedMouseleave.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDelayedMouseleave.directive.js
new file mode 100644
index 0000000000..8493e49d77
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDelayedMouseleave.directive.js
@@ -0,0 +1,49 @@
+(function () {
+ 'use strict';
+
+ function onDelayedMouseleaveDirective($timeout, $parse){
+
+ function link(scope, element, attrs, ctrl) {
+ var active = false;
+ var fn = $parse(attrs.onDelayedMouseleave);
+
+ var leave_f = function (event) {
+ var callback = function () {
+ fn(scope, { $event: event });
+ };
+
+ active = false;
+ $timeout(function () {
+ if (active === false) {
+ scope.$apply(callback);
+ }
+ }, 650);
+ };
+
+ var enter_f = function (event, args) {
+ active = true;
+ };
+
+
+ element.on("mouseleave", leave_f);
+ element.on("mouseenter", enter_f);
+
+ //unsub events
+ scope.$on("$destroy", function () {
+ element.off("mouseleave", leave_f);
+ element.off("mouseenter", enter_f);
+ });
+ }
+
+ var directive = {
+ restrict: 'A',
+ link: link
+ };
+
+ return directive;
+
+ }
+
+ angular.module('umbraco.directives').directive('onDelayedMouseleave', onDelayedMouseleaveDirective);
+
+})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnd.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnd.directive.js
new file mode 100644
index 0000000000..84501e10d6
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnd.directive.js
@@ -0,0 +1,24 @@
+(function () {
+ 'use strict';
+
+ function onDragEndDirective(){
+
+ function link(scope, elm, attrs) {
+ var f = function () {
+ scope.$apply(attrs.onDragEnd);
+ };
+ elm.on("dragend", f);
+ scope.$on("$destroy", function () { elm.off("dragend", f); });
+ }
+
+ var directive = {
+ link: link
+ };
+
+ return directive;
+
+ }
+
+ angular.module('umbraco.directives').directive('onDragEnd', onDragEndDirective);
+
+})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnter.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnter.directive.js
new file mode 100644
index 0000000000..03ae9465d0
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragEnter.directive.js
@@ -0,0 +1,24 @@
+(function () {
+ 'use strict';
+
+ function onDragEnterDirective(){
+
+ function link(scope, elm, attrs) {
+ var f = function () {
+ scope.$apply(attrs.onDragEnter);
+ };
+ elm.on("dragenter", f);
+ scope.$on("$destroy", function () { elm.off("dragenter", f); });
+ }
+
+ var directive = {
+ link: link
+ };
+
+ return directive;
+
+ }
+
+ angular.module('umbraco.directives').directive('onDragEnter', onDragEnterDirective);
+
+})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragLeave.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragLeave.directive.js
new file mode 100644
index 0000000000..cd05ed9289
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragLeave.directive.js
@@ -0,0 +1,40 @@
+(function () {
+ 'use strict';
+
+ function onDragLeaveDirective($timeout){
+
+ return function (scope, elm, attrs) {
+ var f = function (event) {
+ var rect = this.getBoundingClientRect();
+ var getXY = function getCursorPosition(event) {
+ var x, y;
+
+ if (typeof event.clientX === 'undefined') {
+ // try touch screen
+ x = event.pageX + document.documentElement.scrollLeft;
+ y = event.pageY + document.documentElement.scrollTop;
+ } else {
+ x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
+ y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
+ }
+
+ return { x: x, y: y };
+ };
+
+ var e = getXY(event.originalEvent);
+
+ // Check the mouseEvent coordinates are outside of the rectangle
+ if (e.x > rect.left + rect.width - 1 || e.x < rect.left || e.y > rect.top + rect.height - 1 || e.y < rect.top) {
+ scope.$apply(attrs.onDragLeave);
+ }
+ };
+
+ elm.on("dragleave", f);
+ scope.$on("$destroy", function () { elm.off("dragleave", f); });
+ };
+
+ }
+
+ angular.module('umbraco.directives').directive('onDragLeave', onDragLeaveDirective);
+
+})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragOver.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragOver.directive.js
new file mode 100644
index 0000000000..faf9050b8e
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragOver.directive.js
@@ -0,0 +1,24 @@
+(function () {
+ 'use strict';
+
+ function onDragOverDirective(){
+
+ function link(scope, elm, attrs) {
+ var f = function () {
+ scope.$apply(attrs.onDragOver);
+ };
+ elm.on("dragover", f);
+ scope.$on("$destroy", function () { elm.off("dragover", f); });
+ }
+
+ var directive = {
+ link: link
+ };
+
+ return directive;
+
+ }
+
+ angular.module('umbraco.directives').directive('onDragOver', onDragOverDirective);
+
+})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragStart.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragStart.directive.js
new file mode 100644
index 0000000000..8da6211c08
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDragStart.directive.js
@@ -0,0 +1,24 @@
+(function () {
+ 'use strict';
+
+ function onDragStartDirective($timeout){
+
+ function link(scope, elm, attrs) {
+ var f = function () {
+ scope.$apply(attrs.onDragStart);
+ };
+ elm.on("dragstart", f);
+ scope.$on("$destroy", function () { elm.off("dragstart", f); });
+ }
+
+ var directive = {
+ link: link
+ };
+
+ return directive;
+
+ }
+
+ angular.module('umbraco.directives').directive('onDragStart', onDragStartDirective);
+
+})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDrop.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDrop.directive.js
new file mode 100644
index 0000000000..632549f21b
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onDrop.directive.js
@@ -0,0 +1,24 @@
+(function () {
+ 'use strict';
+
+ function onDropDirective(){
+
+ function link(scope, elm, attrs) {
+ var f = function () {
+ scope.$apply(attrs.onDrop);
+ };
+ elm.on("drop", f);
+ scope.$on("$destroy", function () { elm.off("drop", f); });
+ }
+
+ var directive = {
+ link: link
+ };
+
+ return directive;
+
+ }
+
+ angular.module('umbraco.directives').directive('onDrop', onDropDirective);
+
+})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onOutsideClick.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onOutsideClick.directive.js
new file mode 100644
index 0000000000..a657fcbc55
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onOutsideClick.directive.js
@@ -0,0 +1,86 @@
+(function () {
+ 'use strict';
+
+ function onOutsideClickDirective($timeout, angularHelper){
+
+ return function (scope, element, attrs) {
+
+ var eventBindings = [];
+
+ function oneTimeClick(event) {
+ var el = event.target.nodeName;
+
+ //ignore link and button clicks
+ var els = ["INPUT", "A", "BUTTON"];
+ if (els.indexOf(el) >= 0) { return; }
+
+ // ignore clicks on new overlay
+ var parents = $(event.target).parents("a,button,.umb-overlay,.umb-tour");
+ if (parents.length > 0) {
+ return;
+ }
+
+ // ignore clicks on dialog from old dialog service
+ var oldDialog = $(event.target).parents("#old-dialog-service");
+ if (oldDialog.length === 1) {
+ return;
+ }
+
+ // ignore clicks in tinyMCE dropdown(floatpanel)
+ var floatpanel = $(event.target).closest(".mce-floatpanel");
+ if (floatpanel.length === 1) {
+ 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;
+ }
+
+ // please to not use angularHelper.safeApply here, it won't work
+ scope.$apply(attrs.onOutsideClick);
+ }
+
+
+ $timeout(function () {
+
+ if ("bindClickOn" in attrs) {
+
+ eventBindings.push(scope.$watch(function () {
+ return attrs.bindClickOn;
+ }, function (newValue) {
+ if (newValue === "true") {
+ $(document).on("click", oneTimeClick);
+ } else {
+ $(document).off("click", oneTimeClick);
+ }
+ }));
+
+ } else {
+ $(document).on("click", oneTimeClick);
+ }
+
+ scope.$on("$destroy", function () {
+ $(document).off("click", oneTimeClick);
+
+ // unbind watchers
+ for (var e in eventBindings) {
+ eventBindings[e]();
+ }
+
+ });
+ }); // Temp removal of 1 sec timeout to prevent bug where overlay does not open. We need to find a better solution.
+
+ };
+
+ }
+
+ angular.module('umbraco.directives').directive('onOutsideClick', onOutsideClickDirective);
+
+})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onRightClick.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onRightClick.directive.js
new file mode 100644
index 0000000000..6b818997d7
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/onRightClick.directive.js
@@ -0,0 +1,30 @@
+(function () {
+ 'use strict';
+
+ function onRightClickDirective($parse){
+
+ document.oncontextmenu = function (e) {
+ if (e.target.hasAttribute('on-right-click')) {
+ e.preventDefault();
+ e.stopPropagation();
+ return false;
+ }
+ };
+
+ return function (scope, el, attrs) {
+ el.on('contextmenu', function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ var fn = $parse(attrs.onRightClick);
+ scope.$apply(function () {
+ fn(scope, { $event: e });
+ });
+ return false;
+ });
+ };
+
+ }
+
+ angular.module('umbraco.directives').directive('onRightClick', onRightClickDirective);
+
+})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js
index d1f35f8e03..32d3e83dac 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js
@@ -418,6 +418,10 @@
};
+ scope.canRemoveGroup = function(group){
+ return _.find(group.properties, function(property) { return property.locked === true; }) == null;
+ }
+
scope.removeGroup = function(groupIndex) {
scope.model.groups.splice(groupIndex, 1);
};
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js
index 766c0107b2..1b011d2e19 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js
@@ -193,6 +193,9 @@ Use this directive to generate a thumbnail grid of media items.
* Returns wether a item should be selectable or not.
*/
function getSelectableState(item) {
+ if (item.filtered) {
+ return false;
+ }
// check if item is a folder or image
if (item.isFolder === true) {
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbminilistview.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbminilistview.directive.js
index 9c140d572e..1142863bd0 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbminilistview.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbminilistview.directive.js
@@ -77,8 +77,7 @@
}
}
- // filter items if there is a filter and it's not advanced
- // ** ignores advanced filter at the moment
+ // filter items if there is a filter and it's not advanced (advanced filtering is handled below)
if (scope.entityTypeFilter && scope.entityTypeFilter.filter && !scope.entityTypeFilter.filterAdvanced) {
var a = scope.entityTypeFilter.filter.toLowerCase().replace(/\s/g, '').split(',');
var found = a.indexOf(c.metaData.ContentTypeAlias.toLowerCase()) >= 0;
@@ -88,6 +87,15 @@
}
}
});
+
+ // advanced item filtering is handled here
+ if (scope.entityTypeFilter && scope.entityTypeFilter.filter && scope.entityTypeFilter.filterAdvanced) {
+ var filtered = angular.isFunction(scope.entityTypeFilter.filter)
+ ? _.filter(miniListView.children, scope.entityTypeFilter.filter)
+ : _.where(miniListView.children, scope.entityTypeFilter.filter);
+ _.each(filtered, (node) => node.allowed = false);
+ }
+
// update pagination
miniListView.pagination.totalItems = data.totalItems;
miniListView.pagination.totalPages = data.totalPages;
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js
index 6360b429b9..7aa23cad7c 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js
@@ -298,7 +298,8 @@
* Called when the file collection changes (i.e. a new file has been selected but maybe it wasn't this instance that caused the change)
*/
onFilesChanged: "&",
- onInit: "&"
+ onInit: "&",
+ required: "@"
},
transclude: true,
controllerAs: 'vm',
diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js
index 601ff2f671..3874ff9bf6 100644
--- a/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js
+++ b/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js
@@ -187,7 +187,6 @@ angular.module('umbraco.mocks').
"defaultdialogs_linkinternal": "Internal link:",
"defaultdialogs_linklocaltip": "When using local links, insert '#' infront of link",
"defaultdialogs_linknewwindow": "Open in new window?",
- "defaultdialogs_macroContainerSettings": "Macro Settings",
"defaultdialogs_macroDoesNotHaveProperties": "This macro does not contain any properties you can edit",
"defaultdialogs_paste": "Paste",
"defaultdialogs_permissionsEdit": "Edit Permissions for",
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 5d790070b5..20a47ae32c 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
@@ -464,6 +464,8 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt
"properties",
"apps",
"createDateFormatted",
+ "releaseDateFormatted",
+ "expireDateFormatted",
"releaseDate",
"expireDate"
], function (i) {
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js
index ca4108e18c..bcfd9544a2 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js
@@ -898,6 +898,27 @@ When building a custom infinite editor view you can use the same components as a
open(editor);
}
+ /**
+ * @ngdoc method
+ * @name umbraco.services.editorService#memberEditor
+ * @methodOf umbraco.services.editorService
+ *
+ * @description
+ * Opens a member editor in infinite editing, the submit callback returns the updated member
+ * @param {Object} editor rendering options
+ * @param {String} editor.id The id (GUID) of the member
+ * @param {Boolean} editor.create Create new member
+ * @param {Function} editor.submit Callback function when the submit button is clicked. Returns the editor model object
+ * @param {Function} editor.close Callback function when the close button is clicked.
+ * @param {String} editor.doctype If editor.create is true, provide member type for the creation of the member
+ *
+ * @returns {Object} editor object
+ */
+ function memberEditor(editor) {
+ editor.view = "views/member/edit.html";
+ open(editor);
+ }
+
///////////////////////
/**
@@ -978,7 +999,8 @@ When building a custom infinite editor view you can use the same components as a
itemPicker: itemPicker,
macroPicker: macroPicker,
memberGroupPicker: memberGroupPicker,
- memberPicker: memberPicker
+ memberPicker: memberPicker,
+ memberEditor: memberEditor
};
return service;
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js
index da013d88ee..4ff5a05522 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js
@@ -588,12 +588,15 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
var selectedElm = editor.selection.getNode(),
- currentTarget;
+ currentTarget,
+ imgDomElement;
if (selectedElm.nodeName === 'IMG') {
var img = $(selectedElm);
+ imgDomElement = selectedElm;
var hasUdi = img.attr("data-udi") ? true : false;
+ var hasDataTmpImg = img.attr("data-tmpimg") ? true : false;
currentTarget = {
altText: img.attr("alt"),
@@ -605,12 +608,16 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
} else {
currentTarget["id"] = img.attr("rel");
}
+
+ if(hasDataTmpImg){
+ currentTarget["tmpimg"] = img.attr("data-tmpimg");
+ }
}
userService.getCurrentUser().then(function (userData) {
if (callback) {
angularHelper.safeApply($rootScope, function() {
- callback(currentTarget, userData);
+ callback(currentTarget, userData, imgDomElement);
});
}
});
@@ -618,25 +625,77 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
});
},
- insertMediaInEditor: function (editor, img) {
+ insertMediaInEditor: function (editor, img, imgDomElement) {
if (img) {
+ // imgElement is only definied if updating an image
+ // if null/undefinied then its a BRAND new image
+ if(imgDomElement){
+ // Check if the img src has changed
+ // If it has we will need to do some resizing/recalc again
+ var hasImageSrcChanged = false;
- var data = {
- alt: img.altText || "",
- src: (img.url) ? img.url : "nothing.jpg",
- id: '__mcenew',
- 'data-udi': img.udi
- };
+ if(img.url !== editor.dom.getAttrib(imgDomElement, "src")){
+ hasImageSrcChanged = true;
+ }
- editor.selection.setContent(editor.dom.createHTML('img', data));
+ // If null/undefinied it will remove the attribute
+ editor.dom.setAttrib(imgDomElement, "alt", img.altText);
- $timeout(function () {
- var imgElm = editor.dom.get('__mcenew');
- sizeImageInEditor(editor, imgElm, img.url);
- editor.dom.setAttrib(imgElm, 'id', null);
- editor.fire('Change');
+ // It's possible to pick a NEW image - so need to ensure this gets updated
+ if(img.udi){
+ editor.dom.setAttrib(imgDomElement, "data-udi", img.udi);
+ }
- }, 500);
+ // It's possible to pick a NEW image - so need to ensure this gets updated
+ if(img.url){
+ editor.dom.setAttrib(imgDomElement, "src", img.url);
+ }
+
+ // Remove width & height attributes (ONLY if imgSrc changed)
+ // So native image size is used as this needed to re-calc width & height
+ // For the function sizeImageInEditor() & apply the image resizing querystrings etc..
+ if(hasImageSrcChanged){
+ editor.dom.setAttrib(imgDomElement, "width", null);
+ editor.dom.setAttrib(imgDomElement, "height", null);
+
+ //Re-calc the image dimensions
+ sizeImageInEditor(editor, imgDomElement, img.url);
+ }
+
+ } else{
+ // We need to create a NEW DOM