").after(lnk);
- }
- };
-
- return directive;
-
- }
-
- angular.module('umbraco.directives').directive('umbPasswordToggle', PasswordToggleDirective);
-
-})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js
index 0003658600..21a1f181a6 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbrangeslider.directive.js
@@ -57,13 +57,13 @@ For extra details about options and events take a look here: https://refreshless
**/
-(function() {
- 'use strict';
+(function () {
+ 'use strict';
- var umbRangeSlider = {
+ var umbRangeSlider = {
template: '
',
- controller: UmbRangeSliderController,
- bindings: {
+ controller: UmbRangeSliderController,
+ bindings: {
ngModel: '<',
options: '<',
onSetup: '&?',
@@ -73,15 +73,15 @@ For extra details about options and events take a look here: https://refreshless
onChange: '&?',
onStart: '&?',
onEnd: '&?'
- }
+ }
};
-
- function UmbRangeSliderController($element, $timeout, $scope, assetsService) {
-
+
+ function UmbRangeSliderController($element, $timeout, $scope, assetsService) {
+
const ctrl = this;
let sliderInstance = null;
- ctrl.$onInit = function() {
+ ctrl.$onInit = function () {
// load css file for the date picker
assetsService.loadCss('lib/nouislider/nouislider.min.css', $scope);
@@ -94,13 +94,13 @@ For extra details about options and events take a look here: https://refreshless
};
- function grabElementAndRun() {
- $timeout(function() {
+ function grabElementAndRun() {
+ $timeout(function () {
const element = $element.find('.umb-range-slider')[0];
- setSlider(element);
- }, 0, true);
+ setSlider(element);
+ }, 0, true);
}
-
+
function setSlider(element) {
sliderInstance = element;
@@ -117,82 +117,82 @@ For extra details about options and events take a look here: https://refreshless
// create new slider
noUiSlider.create(sliderInstance, options);
-
- if (ctrl.onSetup) {
- ctrl.onSetup({
- slider: sliderInstance
- });
+
+ if (ctrl.onSetup) {
+ ctrl.onSetup({
+ slider: sliderInstance
+ });
}
// If has ngModel set the date
- if (ctrl.ngModel) {
+ if (ctrl.ngModel) {
sliderInstance.noUiSlider.set(ctrl.ngModel);
}
// destroy the slider instance when the dom element is removed
- angular.element(element).on('$destroy', function() {
+ $(element).on('$destroy', function () {
sliderInstance.noUiSlider.off();
});
setUpCallbacks();
- // Refresh the scope
- $scope.$applyAsync();
+ // Refresh the scope
+ $scope.$applyAsync();
}
-
+
function setUpCallbacks() {
- if(sliderInstance) {
+ if (sliderInstance) {
// bind hook for update
- if(ctrl.onUpdate) {
- sliderInstance.noUiSlider.on('update', function (values, handle, unencoded, tap, positions) {
- $timeout(function() {
- ctrl.onUpdate({values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions});
+ if (ctrl.onUpdate) {
+ sliderInstance.noUiSlider.on('update', function (values, handle, unencoded, tap, positions) {
+ $timeout(function () {
+ ctrl.onUpdate({ values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions });
});
});
}
// bind hook for slide
- if(ctrl.onSlide) {
- sliderInstance.noUiSlider.on('slide', function (values, handle, unencoded, tap, positions) {
- $timeout(function() {
- ctrl.onSlide({values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions});
+ if (ctrl.onSlide) {
+ sliderInstance.noUiSlider.on('slide', function (values, handle, unencoded, tap, positions) {
+ $timeout(function () {
+ ctrl.onSlide({ values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions });
});
});
}
// bind hook for set
- if(ctrl.onSet) {
- sliderInstance.noUiSlider.on('set', function (values, handle, unencoded, tap, positions) {
- $timeout(function() {
- ctrl.onSet({values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions});
+ if (ctrl.onSet) {
+ sliderInstance.noUiSlider.on('set', function (values, handle, unencoded, tap, positions) {
+ $timeout(function () {
+ ctrl.onSet({ values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions });
});
});
}
// bind hook for change
- if(ctrl.onChange) {
- sliderInstance.noUiSlider.on('change', function (values, handle, unencoded, tap, positions) {
- $timeout(function() {
- ctrl.onChange({values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions});
+ if (ctrl.onChange) {
+ sliderInstance.noUiSlider.on('change', function (values, handle, unencoded, tap, positions) {
+ $timeout(function () {
+ ctrl.onChange({ values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions });
});
});
}
// bind hook for start
- if(ctrl.onStart) {
- sliderInstance.noUiSlider.on('start', function (values, handle, unencoded, tap, positions) {
- $timeout(function() {
- ctrl.onStart({values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions});
+ if (ctrl.onStart) {
+ sliderInstance.noUiSlider.on('start', function (values, handle, unencoded, tap, positions) {
+ $timeout(function () {
+ ctrl.onStart({ values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions });
});
});
}
// bind hook for end
- if(ctrl.onEnd) {
- sliderInstance.noUiSlider.on('end', function (values, handle, unencoded, tap, positions) {
- $timeout(function() {
- ctrl.onEnd({values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions});
+ if (ctrl.onEnd) {
+ sliderInstance.noUiSlider.on('end', function (values, handle, unencoded, tap, positions) {
+ $timeout(function () {
+ ctrl.onEnd({ values: values, handle: handle, unencoded: unencoded, tap: tap, positions: positions });
});
});
}
@@ -201,7 +201,7 @@ For extra details about options and events take a look here: https://refreshless
}
}
-
+
angular.module('umbraco.directives').component('umbRangeSlider', umbRangeSlider);
-
+
})();
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 96a072330b..653b4f427c 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
@@ -26,6 +26,7 @@
fileManager.setFiles({
propertyAlias: vm.propertyAlias,
culture: vm.culture,
+ segment: vm.segment,
files: []
});
//clear the current files
@@ -92,6 +93,11 @@
vm.culture = null;
}
+ //normalize segment to null if it's not there
+ if (!vm.segment) {
+ vm.segment = null;
+ }
+
// TODO: need to figure out what we can do for things like Nested Content
var existingClientFiles = checkPendingClientFiles();
@@ -134,11 +140,16 @@
vm.culture = null;
}
+ //normalize segment to null if it's not there
+ if (!vm.segment) {
+ vm.segment = null;
+ }
+
//check the file manager to see if there's already local files pending for this editor
var existingClientFiles = _.map(
_.filter(fileManager.getFiles(),
function (f) {
- return f.alias === vm.propertyAlias && f.culture === vm.culture;
+ return f.alias === vm.propertyAlias && f.culture === vm.culture && f.segment === vm.segment;
}),
function (f) {
return f.file;
@@ -264,7 +275,8 @@
fileManager.setFiles({
propertyAlias: vm.propertyAlias,
files: args.files,
- culture: vm.culture
+ culture: vm.culture,
+ segment: vm.segment
});
updateModelFromSelectedFiles(args.files).then(function(newVal) {
@@ -287,6 +299,7 @@
templateUrl: 'views/components/upload/umb-property-file-upload.html',
bindings: {
culture: "@?",
+ segment: "@?",
propertyAlias: "@",
value: "<",
hideSelection: "<",
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js
index 97eb2bf708..8cbdabbf75 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js
@@ -56,7 +56,7 @@
}
//set the model defaults
- if (!angular.isObject(vm.passwordValues)) {
+ if (!Utilities.isObject(vm.passwordValues)) {
//if it's not an object then just create a new one
vm.passwordValues = {
newPassword: null,
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/util/autoscale.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/util/autoscale.directive.js
index 029a4e420f..023692be86 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/util/autoscale.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/util/autoscale.directive.js
@@ -21,7 +21,7 @@ angular.module("umbraco.directives")
var totalOffset = 0;
var offsety = parseInt(attrs.autoScale, 10);
- var window = angular.element($window);
+ var window = $($window);
if (offsety !== undefined) {
totalOffset += offsety;
}
@@ -34,7 +34,7 @@ angular.module("umbraco.directives")
el.height(window.height() - (el.offset().top + totalOffset));
}
- var resizeCallback = function() {
+ var resizeCallback = function () {
setElementSize();
};
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/util/disabletabindex.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/util/disabletabindex.directive.js
index 759d05df71..d43282715e 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/util/disabletabindex.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/util/disabletabindex.directive.js
@@ -1,46 +1,46 @@
angular.module("umbraco.directives")
.directive('disableTabindex', function (tabbableService) {
- return {
- restrict: 'A', //Can only be used as an attribute,
- scope: {
- "disableTabindex": "<"
- },
- link: function (scope, element, attrs) {
+ return {
+ restrict: 'A', //Can only be used as an attribute,
+ scope: {
+ "disableTabindex": "<"
+ },
+ link: function (scope, element, attrs) {
- if(scope.disableTabindex) {
- //Select the node that will be observed for mutations (native DOM element not jQLite version)
- var targetNode = element[0];
+ if (scope.disableTabindex) {
+ //Select the node that will be observed for mutations (native DOM element not jQLite version)
+ var targetNode = element[0];
- //Watch for DOM changes - so when the property editor subview loads in
- //We can be notified its updated the child elements inside the DIV we are watching
- var observer = new MutationObserver(domChange);
+ //Watch for DOM changes - so when the property editor subview loads in
+ //We can be notified its updated the child elements inside the DIV we are watching
+ var observer = new MutationObserver(domChange);
- // Options for the observer (which mutations to observe)
- var config = { attributes: true, childList: true, subtree: true };
+ // Options for the observer (which mutations to observe)
+ var config = { attributes: true, childList: true, subtree: true };
- function domChange(mutationsList, observer) {
- for(var mutation of mutationsList) {
+ function domChange(mutationsList, observer) {
+ for (var mutation of mutationsList) {
- //DOM items have been added or removed
- if (mutation.type == 'childList') {
+ //DOM items have been added or removed
+ if (mutation.type == 'childList') {
- //Check if any child items in mutation.target contain an input
- var childInputs = tabbableService.tabbable(mutation.target);
+ //Check if any child items in mutation.target contain an input
+ var childInputs = tabbableService.tabbable(mutation.target);
- //For each item in childInputs - override or set HTML attribute tabindex="-1"
- angular.forEach(childInputs, function(element){
- angular.element(element).attr('tabindex', '-1');
- });
+ //For each item in childInputs - override or set HTML attribute tabindex="-1"
+ angular.forEach(childInputs, function (element) {
+ $(element).attr('tabindex', '-1');
+ });
+ }
}
}
+
+ // Start observing the target node for configured mutations
+ //GO GO GO
+ observer.observe(targetNode, config);
}
- // Start observing the target node for configured mutations
- //GO GO GO
- observer.observe(targetNode, config);
}
-
- }
- };
-});
+ };
+ });
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js
index 149c2b5087..30d3530efb 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js
@@ -38,7 +38,8 @@ function valPropertyMsg(serverValidationManager, localizationService) {
var currentProperty = umbPropCtrl.property;
scope.currentProperty = currentProperty;
- var currentCulture = currentProperty.culture;
+ var currentCulture = currentProperty.culture;
+ var currentSegment = currentProperty.segment;
// validation object won't exist when editor loads outside the content form (ie in settings section when modifying a content type)
var isMandatory = currentProperty.validation ? currentProperty.validation.mandatory : undefined;
@@ -54,7 +55,7 @@ function valPropertyMsg(serverValidationManager, localizationService) {
var currentVariant = umbVariantCtrl.editor.content;
// Lets check if we have variants and we are on the default language then ...
- if (umbVariantCtrl.content.variants.length > 1 && !currentVariant.language.isDefault && !currentCulture && !currentProperty.unlockInvariantValue) {
+ if (umbVariantCtrl.content.variants.length > 1 && (!currentVariant.language || !currentVariant.language.isDefault) && !currentCulture && !currentSegment && !currentProperty.unlockInvariantValue) {
//This property is locked cause its a invariant property shown on a non-default language.
//Therefor do not validate this field.
return;
@@ -70,7 +71,7 @@ function valPropertyMsg(serverValidationManager, localizationService) {
//this can be null if no property was assigned
if (scope.currentProperty) {
//first try to get the error msg from the server collection
- var err = serverValidationManager.getPropertyError(scope.currentProperty.alias, null, "");
+ var err = serverValidationManager.getPropertyError(scope.currentProperty.alias, null, "", null);
//if there's an error message use it
if (err && err.errorMsg) {
return err.errorMsg;
@@ -101,7 +102,7 @@ function valPropertyMsg(serverValidationManager, localizationService) {
var errCount = 0;
for (var e in formCtrl.$error) {
- if (angular.isArray(formCtrl.$error[e])) {
+ if (Utilities.isArray(formCtrl.$error[e])) {
errCount++;
}
}
@@ -111,8 +112,8 @@ function valPropertyMsg(serverValidationManager, localizationService) {
// is the only one, then we'll clear.
if (errCount === 0
- || (errCount === 1 && angular.isArray(formCtrl.$error.valPropertyMsg))
- || (formCtrl.$invalid && angular.isArray(formCtrl.$error.valServer))) {
+ || (errCount === 1 && Utilities.isArray(formCtrl.$error.valPropertyMsg))
+ || (formCtrl.$invalid && Utilities.isArray(formCtrl.$error.valServer))) {
scope.errorMsg = "";
formCtrl.$setValidity('valPropertyMsg', true);
} else if (showValidation && scope.errorMsg === "") {
@@ -221,25 +222,31 @@ function valPropertyMsg(serverValidationManager, localizationService) {
// the correct field validation in their property editors.
if (scope.currentProperty) { //this can be null if no property was assigned
+
+ function serverValidationManagerCallback(isValid, propertyErrors, allErrors) {
+ hasError = !isValid;
+ if (hasError) {
+ //set the error message to the server message
+ scope.errorMsg = propertyErrors[0].errorMsg;
+ //flag that the current validator is invalid
+ formCtrl.$setValidity('valPropertyMsg', false);
+ startWatch();
+ }
+ else {
+ scope.errorMsg = "";
+ //flag that the current validator is valid
+ formCtrl.$setValidity('valPropertyMsg', true);
+ stopWatch();
+ }
+ }
+
unsubscribe.push(serverValidationManager.subscribe(scope.currentProperty.alias,
currentCulture,
"",
- function(isValid, propertyErrors, allErrors) {
- hasError = !isValid;
- if (hasError) {
- //set the error message to the server message
- scope.errorMsg = propertyErrors[0].errorMsg;
- //flag that the current validator is invalid
- formCtrl.$setValidity('valPropertyMsg', false);
- startWatch();
- }
- else {
- scope.errorMsg = "";
- //flag that the current validator is valid
- formCtrl.$setValidity('valPropertyMsg', true);
- stopWatch();
- }
- }));
+ serverValidationManagerCallback,
+ currentSegment
+ )
+ );
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js
index a0cc7e3033..3fa9220f7b 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js
@@ -24,6 +24,7 @@ function valServer(serverValidationManager) {
var currentProperty = umbPropCtrl.property;
var currentCulture = currentProperty.culture;
+ var currentSegment = currentProperty.segment;
if (umbVariantCtrl) {
//if we are inside of an umbVariantContent directive
@@ -31,7 +32,7 @@ function valServer(serverValidationManager) {
var currentVariant = umbVariantCtrl.editor.content;
// Lets check if we have variants and we are on the default language then ...
- if (umbVariantCtrl.content.variants.length > 1 && !currentVariant.language.isDefault && !currentCulture && !currentProperty.unlockInvariantValue) {
+ if (umbVariantCtrl.content.variants.length > 1 && (!currentVariant.language || !currentVariant.language.isDefault) && !currentCulture && !currentSegment && !currentProperty.unlockInvariantValue) {
//This property is locked cause its a invariant property shown on a non-default language.
//Therefor do not validate this field.
return;
@@ -75,7 +76,7 @@ function valServer(serverValidationManager) {
if (modelCtrl.$invalid) {
modelCtrl.$setValidity('valServer', true);
//clear the server validation entry
- serverValidationManager.removePropertyError(currentProperty.alias, currentCulture, fieldName);
+ serverValidationManager.removePropertyError(currentProperty.alias, currentCulture, fieldName, currentSegment);
stopWatch();
}
}, true);
@@ -90,23 +91,26 @@ function valServer(serverValidationManager) {
}
//subscribe to the server validation changes
+ function serverValidationManagerCallback(isValid, propertyErrors, allErrors) {
+ if (!isValid) {
+ modelCtrl.$setValidity('valServer', false);
+ //assign an error msg property to the current validator
+ modelCtrl.errorMsg = propertyErrors[0].errorMsg;
+ startWatch();
+ }
+ else {
+ modelCtrl.$setValidity('valServer', true);
+ //reset the error message
+ modelCtrl.errorMsg = "";
+ stopWatch();
+ }
+ }
unsubscribe.push(serverValidationManager.subscribe(currentProperty.alias,
currentCulture,
fieldName,
- function(isValid, propertyErrors, allErrors) {
- if (!isValid) {
- modelCtrl.$setValidity('valServer', false);
- //assign an error msg property to the current validator
- modelCtrl.errorMsg = propertyErrors[0].errorMsg;
- startWatch();
- }
- else {
- modelCtrl.$setValidity('valServer', true);
- //reset the error message
- modelCtrl.errorMsg = "";
- stopWatch();
- }
- }));
+ serverValidationManagerCallback,
+ currentSegment)
+ );
scope.$on('$destroy', function () {
stopWatch();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js
index 524b5f7efe..1f5aaaa1c2 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js
@@ -40,7 +40,7 @@
function link(scope, el, attr, ctrl) {
//if there are no containing form or valFormManager controllers, then we do nothing
- if (!ctrl || !angular.isArray(ctrl) || ctrl.length !== 2 || !ctrl[0] || !ctrl[1]) {
+ if (!ctrl || !Utilities.isArray(ctrl) || ctrl.length !== 2 || !ctrl[0] || !ctrl[1]) {
return;
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/filters/umbCmsJoinArray.filter.js b/src/Umbraco.Web.UI.Client/src/common/filters/umbCmsJoinArray.filter.js
index de340bab27..a519f81054 100644
--- a/src/Umbraco.Web.UI.Client/src/common/filters/umbCmsJoinArray.filter.js
+++ b/src/Umbraco.Web.UI.Client/src/common/filters/umbCmsJoinArray.filter.js
@@ -1,6 +1,6 @@
/**
* @ngdoc filter
- * @name umbraco.filters.filter:CMS_joinArray
+ * @name umbraco.filters.filter:umbCmsJoinArray
* @namespace umbCmsJoinArray
*
* param {array} array of string or objects, if an object use the third argument to specify which prop to list.
diff --git a/src/Umbraco.Web.UI.Client/src/common/filters/umbCmsTitleCase.filter.js b/src/Umbraco.Web.UI.Client/src/common/filters/umbCmsTitleCase.filter.js
new file mode 100644
index 0000000000..8d2c233655
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/common/filters/umbCmsTitleCase.filter.js
@@ -0,0 +1,19 @@
+/**
+ * @ngdoc filter
+ * @name umbraco.filters.filter:umbCmsTitleCase
+ * @namespace umbCmsTitleCase
+ *
+ * param {string} the text turned into title case.
+ *
+ * @description
+ * Transforms text to title case. Capitalizes the first letter of each word, and transforms the rest of the word to lower case.
+ *
+ */
+angular.module("umbraco.filters").filter('umbCmsTitleCase', function() {
+ return function (str) {
+ return str.replace(
+ /\w\S*/g,
+ txt => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
+ );
+ }
+});
diff --git a/src/Umbraco.Web.UI.Client/src/common/filters/umbwordlimit.filter.js b/src/Umbraco.Web.UI.Client/src/common/filters/umbwordlimit.filter.js
index c02624409f..93f0bddc96 100644
--- a/src/Umbraco.Web.UI.Client/src/common/filters/umbwordlimit.filter.js
+++ b/src/Umbraco.Web.UI.Client/src/common/filters/umbwordlimit.filter.js
@@ -13,7 +13,7 @@
function umbWordLimitFilter() {
return function (collection, property) {
- if (!angular.isString(collection)) {
+ if (!Utilities.isString(collection)) {
return collection;
}
@@ -35,4 +35,4 @@
angular.module('umbraco.filters').filter('umbWordLimit', umbWordLimitFilter);
-})();
\ No newline at end of file
+})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/interceptors/culturerequest.interceptor.js b/src/Umbraco.Web.UI.Client/src/common/interceptors/culturerequest.interceptor.js
index 186f3accf0..283a2a7ae9 100644
--- a/src/Umbraco.Web.UI.Client/src/common/interceptors/culturerequest.interceptor.js
+++ b/src/Umbraco.Web.UI.Client/src/common/interceptors/culturerequest.interceptor.js
@@ -24,6 +24,7 @@
if ($routeParams) {
// it's an API request, add the current client culture as a header value
config.headers["X-UMB-CULTURE"] = $routeParams.cculture ? $routeParams.cculture : $routeParams.mculture;
+ config.headers["X-UMB-SEGMENT"] = $routeParams.csegment ? $routeParams.csegment : null;
}
return config;
diff --git a/src/Umbraco.Web.UI.Client/src/common/interceptors/donotpostdollarvariablesrequest.interceptor.js b/src/Umbraco.Web.UI.Client/src/common/interceptors/donotpostdollarvariablesrequest.interceptor.js
index 03373089d7..f3dd60bdce 100644
--- a/src/Umbraco.Web.UI.Client/src/common/interceptors/donotpostdollarvariablesrequest.interceptor.js
+++ b/src/Umbraco.Web.UI.Client/src/common/interceptors/donotpostdollarvariablesrequest.interceptor.js
@@ -1,40 +1,40 @@
-(function() {
- 'use strict';
-
+(function () {
+ 'use strict';
+
function removeProperty(obj, propertyPrefix) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
-
+
if (property.startsWith(propertyPrefix) && obj[property] !== undefined) {
obj[property] = undefined;
}
-
+
if (typeof obj[property] === "object") {
removeProperty(obj[property], propertyPrefix);
}
}
}
-
+
}
-
- function transform(data){
+
+ function transform(data) {
removeProperty(data, "$");
}
-
+
function doNotPostDollarVariablesRequestInterceptor($q, urlHelper) {
return {
//dealing with requests:
- 'request': function(config) {
- if(config.method === "POST"){
- var clone = angular.copy(config);
+ 'request': function (config) {
+ if (config.method === "POST") {
+ var clone = Utilities.copy(config);
transform(clone.data);
return clone;
}
-
+
return config;
}
};
- }
+ }
angular.module('umbraco.interceptors').factory('doNotPostDollarVariablesOnPostRequestInterceptor', doNotPostDollarVariablesRequestInterceptor);
})();
diff --git a/src/Umbraco.Web.UI.Client/src/common/interceptors/security.interceptor.js b/src/Umbraco.Web.UI.Client/src/common/interceptors/security.interceptor.js
index 30daaf5837..bf748975a1 100644
--- a/src/Umbraco.Web.UI.Client/src/common/interceptors/security.interceptor.js
+++ b/src/Umbraco.Web.UI.Client/src/common/interceptors/security.interceptor.js
@@ -44,7 +44,7 @@
var headers = config.headers ? config.headers : {};
//Here we'll check if we should ignore the error (either based on the original header set or the request configuration)
- if (headers["x-umb-ignore-error"] === "ignore" || config.umbIgnoreErrors === true || (angular.isArray(config.umbIgnoreStatus) && config.umbIgnoreStatus.indexOf(rejection.status) !== -1)) {
+ if (headers["x-umb-ignore-error"] === "ignore" || config.umbIgnoreErrors === true || (Utilities.isArray(config.umbIgnoreStatus) && config.umbIgnoreStatus.indexOf(rejection.status) !== -1)) {
//exit/ignore
return $q.reject(rejection);
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/_utils.js b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/_utils.js
index fc28567ea3..1eb259747e 100644
--- a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/_utils.js
+++ b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/_utils.js
@@ -90,7 +90,7 @@ angular.module('umbraco.mocks').
name: "1 column layout",
sections: [
{
- grid: 12,
+ grid: 12
}
]
},
@@ -98,7 +98,7 @@ angular.module('umbraco.mocks').
name: "2 column layout",
sections: [
{
- grid: 4,
+ grid: 4
},
{
grid: 8
@@ -139,7 +139,7 @@ angular.module('umbraco.mocks').
}
}
- },
+ }
]
},
{
diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/datatype.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/datatype.mocks.js
index 054f0aa66d..e70f483bf4 100644
--- a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/datatype.mocks.js
+++ b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/datatype.mocks.js
@@ -1,113 +1,113 @@
angular.module('umbraco.mocks').
- factory('dataTypeMocks', ['$httpBackend', 'mocksUtils', function ($httpBackend, mocksUtils) {
- 'use strict';
-
- function returnById(status, data, headers) {
+ factory('dataTypeMocks', ['$httpBackend', 'mocksUtils', function ($httpBackend, mocksUtils) {
+ 'use strict';
- if (!mocksUtils.checkAuth()) {
- return [401, null, null];
- }
+ function returnById(status, data, headers) {
- var id = mocksUtils.getParameterByName(data, "id") || 1234;
+ if (!mocksUtils.checkAuth()) {
+ return [401, null, null];
+ }
- var selectedId = String.CreateGuid();
+ var id = mocksUtils.getParameterByName(data, "id") || 1234;
- var dataType = mocksUtils.getMockDataType(id, selectedId);
-
- return [200, dataType, null];
- }
-
- function returnEmpty(status, data, headers) {
+ var selectedId = String.CreateGuid();
- if (!mocksUtils.checkAuth()) {
- return [401, null, null];
- }
+ var dataType = mocksUtils.getMockDataType(id, selectedId);
- var response = returnById(200, "", null);
- var node = response[1];
+ return [200, dataType, null];
+ }
- node.name = "";
- node.selectedEditor = "";
- node.id = 0;
- node.preValues = [];
+ function returnEmpty(status, data, headers) {
- return response;
- }
-
- function returnPreValues(status, data, headers) {
+ if (!mocksUtils.checkAuth()) {
+ return [401, null, null];
+ }
- if (!mocksUtils.checkAuth()) {
- return [401, null, null];
- }
+ var response = returnById(200, "", null);
+ var node = response[1];
- var editorId = mocksUtils.getParameterByName(data, "editorId") || "83E9AD36-51A7-4440-8C07-8A5623AC6979";
+ node.name = "";
+ node.selectedEditor = "";
+ node.id = 0;
+ node.preValues = [];
- var preValues = [
- {
- label: "Custom pre value 1 for editor " + editorId,
- description: "Enter a value for this pre-value",
- key: "myPreVal",
- view: "requiredfield",
- validation: [
- {
- type: "Required"
- }
- ]
- },
- {
- label: "Custom pre value 2 for editor " + editorId,
- description: "Enter a value for this pre-value",
- key: "myPreVal",
- view: "requiredfield",
- validation: [
- {
- type: "Required"
- }
- ]
- }
- ];
- return [200, preValues, null];
- }
-
- function returnSave(status, data, headers) {
- if (!mocksUtils.checkAuth()) {
- return [401, null, null];
- }
+ return response;
+ }
- var postedData = angular.fromJson(headers);
+ function returnPreValues(status, data, headers) {
- var dataType = mocksUtils.getMockDataType(postedData.id, postedData.selectedEditor);
- dataType.notifications = [{
- header: "Saved",
- message: "Data type saved",
- type: 0
- }];
+ if (!mocksUtils.checkAuth()) {
+ return [401, null, null];
+ }
- return [200, dataType, null];
- }
+ var editorId = mocksUtils.getParameterByName(data, "editorId") || "83E9AD36-51A7-4440-8C07-8A5623AC6979";
- return {
- register: function() {
-
- $httpBackend
- .whenPOST(mocksUtils.urlRegex('/umbraco/UmbracoApi/DataType/PostSave'))
- .respond(returnSave);
-
- $httpBackend
- .whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/DataType/GetById'))
- .respond(returnById);
-
- $httpBackend
- .whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/DataType/GetEmpty'))
- .respond(returnEmpty);
-
- $httpBackend
- .whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/DataType/GetPreValues'))
- .respond(returnPreValues);
- },
- expectGetById: function() {
- $httpBackend
- .expectGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/DataType/GetById'));
- }
- };
- }]);
+ var preValues = [
+ {
+ label: "Custom pre value 1 for editor " + editorId,
+ description: "Enter a value for this pre-value",
+ key: "myPreVal",
+ view: "requiredfield",
+ validation: [
+ {
+ type: "Required"
+ }
+ ]
+ },
+ {
+ label: "Custom pre value 2 for editor " + editorId,
+ description: "Enter a value for this pre-value",
+ key: "myPreVal",
+ view: "requiredfield",
+ validation: [
+ {
+ type: "Required"
+ }
+ ]
+ }
+ ];
+ return [200, preValues, null];
+ }
+
+ function returnSave(status, data, headers) {
+ if (!mocksUtils.checkAuth()) {
+ return [401, null, null];
+ }
+
+ var postedData = JSON.parse(headers);
+
+ var dataType = mocksUtils.getMockDataType(postedData.id, postedData.selectedEditor);
+ dataType.notifications = [{
+ header: "Saved",
+ message: "Data type saved",
+ type: 0
+ }];
+
+ return [200, dataType, null];
+ }
+
+ return {
+ register: function () {
+
+ $httpBackend
+ .whenPOST(mocksUtils.urlRegex('/umbraco/UmbracoApi/DataType/PostSave'))
+ .respond(returnSave);
+
+ $httpBackend
+ .whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/DataType/GetById'))
+ .respond(returnById);
+
+ $httpBackend
+ .whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/DataType/GetEmpty'))
+ .respond(returnEmpty);
+
+ $httpBackend
+ .whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/DataType/GetPreValues'))
+ .respond(returnPreValues);
+ },
+ expectGetById: function () {
+ $httpBackend
+ .expectGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/DataType/GetById'));
+ }
+ };
+ }]);
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js
index 678cffe42e..936f69e738 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js
@@ -30,7 +30,7 @@ function authResource($q, $http, umbRequestHelper, angularHelper) {
umbRequestHelper.getApiUrl(
"authenticationApiBaseUrl",
"PostSend2FACode"),
- angular.toJson(provider)),
+ Utilities.toJson(provider)),
'Could not send code');
},
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js
index d714ea4938..7bc2a9d2c8 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js
@@ -610,10 +610,10 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
//converts the value to a js bool
function toBool(v) {
- if (angular.isNumber(v)) {
+ if (Utilities.isNumber(v)) {
return v > 0;
}
- if (angular.isString(v)) {
+ if (Utilities.isString(v)) {
return v === "true";
}
if (typeof v === "boolean") {
@@ -1003,10 +1003,10 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
loginPageId: loginPageId,
errorPageId: errorPageId
};
- if (angular.isArray(groups) && groups.length) {
+ if (Utilities.isArray(groups) && groups.length) {
publicAccess.groups = groups;
}
- else if (angular.isArray(usernames) && usernames.length) {
+ else if (Utilities.isArray(usernames) && usernames.length) {
publicAccess.usernames = usernames;
}
else {
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/currentuser.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/currentuser.resource.js
index e10837ceca..60b87e919f 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/currentuser.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/currentuser.resource.js
@@ -87,7 +87,7 @@ function currentUserResource($q, $http, umbRequestHelper, umbDataFormatter) {
umbRequestHelper.getApiUrl(
"currentUserApiBaseUrl",
"PostSetInvitedUserPassword"),
- angular.toJson(newPassword)),
+ Utilities.toJson(newPassword)),
'Failed to change password');
},
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js
index e4e3cc6f3f..e24f4786eb 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js
@@ -348,10 +348,10 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
//converts the value to a js bool
function toBool(v) {
- if (angular.isNumber(v)) {
+ if (Utilities.isNumber(v)) {
return v > 0;
}
- if (angular.isString(v)) {
+ if (Utilities.isString(v)) {
return v === "true";
}
if (typeof v === "boolean") {
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js
index d21edbbab8..c45e173a98 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js
@@ -53,10 +53,10 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
//converts the value to a js bool
function toBool(v) {
- if (angular.isNumber(v)) {
+ if (Utilities.isNumber(v)) {
return v > 0;
}
- if (angular.isString(v)) {
+ if (Utilities.isString(v)) {
return v === "true";
}
if (typeof v === "boolean") {
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js
index 8cba83328f..f2ff711ac9 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js
@@ -33,7 +33,7 @@ function angularHelper($q) {
//this is sequential promise chaining, it's not pretty but we need to do it this way.
//$q.all doesn't execute promises in sequence but that's what we want to do here.
- if (!angular.isArray(promises)) {
+ if (!Utilities.isArray(promises)) {
throw "promises must be an array";
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js b/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js
index 6673002981..30e59e9a88 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js
@@ -256,7 +256,7 @@ angular.module('umbraco.services')
load: function (pathArray, scope, defaultAssetType) {
var promise;
- if (!angular.isArray(pathArray)) {
+ if (!Utilities.isArray(pathArray)) {
throw "pathArray must be an array";
}
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 20a47ae32c..bfcc0d536e 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
@@ -10,7 +10,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt
function isValidIdentifier(id) {
//empty id <= 0
- if (angular.isNumber(id)) {
+ if (Utilities.isNumber(id)) {
if (id === 0) {
return false;
}
@@ -39,7 +39,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt
/** Used by the content editor and mini content editor to perform saving operations */
contentEditorPerformSave: function (args) {
- if (!angular.isObject(args)) {
+ if (!Utilities.isObject(args)) {
throw "args must be an object";
}
if (!args.scope) {
@@ -152,7 +152,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt
here we'll build the buttons according to the chars of the user. */
configureContentEditorButtons: function (args) {
- if (!angular.isObject(args)) {
+ if (!Utilities.isObject(args)) {
throw "args must be an object";
}
if (!args.content) {
@@ -328,9 +328,11 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt
*
* @description
* Returns a id for the variant that is unique between all variants on the content
+ * Note "invariant" is used for the invariant culture,
+ * "null" is used for the NULL segment
*/
buildCompositeVariantId: function (variant) {
- return (variant.language ? variant.language.culture : "invariant") + "_" + (variant.segment ? variant.segment : "");
+ return (variant.language ? variant.language.culture : "invariant") + "_" + (variant.segment ? variant.segment : "null");
},
@@ -698,7 +700,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt
// /belle/#/content/edit/9876 (where 9876 is the new id)
//clear the query strings
- navigationService.clearSearch(["cculture"]);
+ navigationService.clearSearch(["cculture", "csegment"]);
if (softRedirect) {
navigationService.setSoftRedirect();
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenttypehelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenttypehelper.service.js
index 305e4a694d..1be66cc68f 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/contenttypehelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/contenttypehelper.service.js
@@ -7,21 +7,21 @@ function contentTypeHelper(contentTypeResource, dataTypeResource, $filter, $inje
var contentTypeHelperService = {
- createIdArray: function(array) {
+ createIdArray: function (array) {
- var newArray = [];
+ var newArray = [];
- angular.forEach(array, function(arrayItem){
+ angular.forEach(array, function (arrayItem) {
- if(angular.isObject(arrayItem)) {
- newArray.push(arrayItem.id);
- } else {
- newArray.push(arrayItem);
- }
+ if (Utilities.isObject(arrayItem)) {
+ newArray.push(arrayItem.id);
+ } else {
+ newArray.push(arrayItem);
+ }
- });
+ });
- return newArray;
+ return newArray;
},
@@ -30,18 +30,18 @@ function contentTypeHelper(contentTypeResource, dataTypeResource, $filter, $inje
var modelsResource = $injector.has("modelsBuilderManagementResource") ? $injector.get("modelsBuilderManagementResource") : null;
var modelsBuilderEnabled = Umbraco.Sys.ServerVariables.umbracoPlugins.modelsBuilder.enabled;
if (modelsBuilderEnabled && modelsResource) {
- modelsResource.buildModels().then(function(result) {
+ modelsResource.buildModels().then(function (result) {
deferred.resolve(result);
//just calling this to get the servar back to life
modelsResource.getModelsOutOfDateStatus();
- }, function(e) {
+ }, function (e) {
deferred.reject(e);
});
}
- else {
- deferred.resolve(false);
+ else {
+ deferred.resolve(false);
}
return deferred.promise;
},
@@ -49,10 +49,10 @@ function contentTypeHelper(contentTypeResource, dataTypeResource, $filter, $inje
checkModelsBuilderStatus: function () {
var deferred = $q.defer();
var modelsResource = $injector.has("modelsBuilderManagementResource") ? $injector.get("modelsBuilderManagementResource") : null;
- var modelsBuilderEnabled = (Umbraco && Umbraco.Sys && Umbraco.Sys.ServerVariables && Umbraco.Sys.ServerVariables.umbracoPlugins && Umbraco.Sys.ServerVariables.umbracoPlugins.modelsBuilder && Umbraco.Sys.ServerVariables.umbracoPlugins.modelsBuilder.enabled === true);
-
+ var modelsBuilderEnabled = (Umbraco && Umbraco.Sys && Umbraco.Sys.ServerVariables && Umbraco.Sys.ServerVariables.umbracoPlugins && Umbraco.Sys.ServerVariables.umbracoPlugins.modelsBuilder && Umbraco.Sys.ServerVariables.umbracoPlugins.modelsBuilder.enabled === true);
+
if (modelsBuilderEnabled && modelsResource) {
- modelsResource.getModelsOutOfDateStatus().then(function(result) {
+ modelsResource.getModelsOutOfDateStatus().then(function (result) {
//Generate models buttons should be enabled if it is 0
deferred.resolve(result.status === 0);
});
@@ -64,37 +64,37 @@ function contentTypeHelper(contentTypeResource, dataTypeResource, $filter, $inje
},
makeObjectArrayFromId: function (idArray, objectArray) {
- var newArray = [];
+ var newArray = [];
- for (var idIndex = 0; idArray.length > idIndex; idIndex++) {
- var id = idArray[idIndex];
+ for (var idIndex = 0; idArray.length > idIndex; idIndex++) {
+ var id = idArray[idIndex];
- for (var objectIndex = 0; objectArray.length > objectIndex; objectIndex++) {
- var object = objectArray[objectIndex];
- if (id === object.id) {
- newArray.push(object);
- }
- }
+ for (var objectIndex = 0; objectArray.length > objectIndex; objectIndex++) {
+ var object = objectArray[objectIndex];
+ if (id === object.id) {
+ newArray.push(object);
+ }
+ }
- }
+ }
- return newArray;
+ return newArray;
},
- validateAddingComposition: function(contentType, compositeContentType) {
+ validateAddingComposition: function (contentType, compositeContentType) {
//Validate that by adding this group that we are not adding duplicate property type aliases
- var propertiesAdding = _.flatten(_.map(compositeContentType.groups, function(g) {
- return _.map(g.properties, function(p) {
+ var propertiesAdding = _.flatten(_.map(compositeContentType.groups, function (g) {
+ return _.map(g.properties, function (p) {
return p.alias;
});
}));
- var propAliasesExisting = _.filter(_.flatten(_.map(contentType.groups, function(g) {
- return _.map(g.properties, function(p) {
+ var propAliasesExisting = _.filter(_.flatten(_.map(contentType.groups, function (g) {
+ return _.map(g.properties, function (p) {
return p.alias;
});
- })), function(f) {
+ })), function (f) {
return f !== null && f !== undefined;
});
@@ -108,7 +108,7 @@ function contentTypeHelper(contentTypeResource, dataTypeResource, $filter, $inje
return [];
},
- mergeCompositeContentType: function(contentType, compositeContentType) {
+ mergeCompositeContentType: function (contentType, compositeContentType) {
//Validate that there are no overlapping aliases
var overlappingAliases = this.validateAddingComposition(contentType, compositeContentType);
@@ -116,107 +116,107 @@ function contentTypeHelper(contentTypeResource, dataTypeResource, $filter, $inje
throw new Error("Cannot add this composition, these properties already exist on the content type: " + overlappingAliases.join());
}
- angular.forEach(compositeContentType.groups, function(compositionGroup) {
+ angular.forEach(compositeContentType.groups, function (compositionGroup) {
- // order composition groups based on sort order
- compositionGroup.properties = $filter('orderBy')(compositionGroup.properties, 'sortOrder');
+ // order composition groups based on sort order
+ compositionGroup.properties = $filter('orderBy')(compositionGroup.properties, 'sortOrder');
- // get data type details
- angular.forEach(compositionGroup.properties, function(property) {
- dataTypeResource.getById(property.dataTypeId)
- .then(function(dataType) {
- property.dataTypeIcon = dataType.icon;
- property.dataTypeName = dataType.name;
- });
- });
+ // get data type details
+ angular.forEach(compositionGroup.properties, function (property) {
+ dataTypeResource.getById(property.dataTypeId)
+ .then(function (dataType) {
+ property.dataTypeIcon = dataType.icon;
+ property.dataTypeName = dataType.name;
+ });
+ });
- // set inherited state on tab
- compositionGroup.inherited = true;
+ // set inherited state on tab
+ compositionGroup.inherited = true;
- // set inherited state on properties
- angular.forEach(compositionGroup.properties, function(compositionProperty) {
- compositionProperty.inherited = true;
- });
+ // set inherited state on properties
+ angular.forEach(compositionGroup.properties, function (compositionProperty) {
+ compositionProperty.inherited = true;
+ });
- // set tab state
- compositionGroup.tabState = "inActive";
+ // set tab state
+ compositionGroup.tabState = "inActive";
- // if groups are named the same - merge the groups
- angular.forEach(contentType.groups, function(contentTypeGroup) {
+ // if groups are named the same - merge the groups
+ angular.forEach(contentType.groups, function (contentTypeGroup) {
- if (contentTypeGroup.name === compositionGroup.name) {
+ if (contentTypeGroup.name === compositionGroup.name) {
- // set flag to show if properties has been merged into a tab
- compositionGroup.groupIsMerged = true;
+ // set flag to show if properties has been merged into a tab
+ compositionGroup.groupIsMerged = true;
- // make group inherited
- contentTypeGroup.inherited = true;
+ // make group inherited
+ contentTypeGroup.inherited = true;
- // add properties to the top of the array
- contentTypeGroup.properties = compositionGroup.properties.concat(contentTypeGroup.properties);
+ // add properties to the top of the array
+ contentTypeGroup.properties = compositionGroup.properties.concat(contentTypeGroup.properties);
- // update sort order on all properties in merged group
- contentTypeGroup.properties = contentTypeHelperService.updatePropertiesSortOrder(contentTypeGroup.properties);
+ // update sort order on all properties in merged group
+ contentTypeGroup.properties = contentTypeHelperService.updatePropertiesSortOrder(contentTypeGroup.properties);
+
+ // make parentTabContentTypeNames to an array so we can push values
+ if (contentTypeGroup.parentTabContentTypeNames === null || contentTypeGroup.parentTabContentTypeNames === undefined) {
+ contentTypeGroup.parentTabContentTypeNames = [];
+ }
+
+ // push name to array of merged composite content types
+ contentTypeGroup.parentTabContentTypeNames.push(compositeContentType.name);
+
+ // make parentTabContentTypes to an array so we can push values
+ if (contentTypeGroup.parentTabContentTypes === null || contentTypeGroup.parentTabContentTypes === undefined) {
+ contentTypeGroup.parentTabContentTypes = [];
+ }
+
+ // push id to array of merged composite content types
+ contentTypeGroup.parentTabContentTypes.push(compositeContentType.id);
+
+ // get sort order from composition
+ contentTypeGroup.sortOrder = compositionGroup.sortOrder;
+
+ // splice group to the top of the array
+ var contentTypeGroupCopy = Utilities.copy(contentTypeGroup);
+ var index = contentType.groups.indexOf(contentTypeGroup);
+ contentType.groups.splice(index, 1);
+ contentType.groups.unshift(contentTypeGroupCopy);
+
+ }
+
+ });
+
+ // if group is not merged - push it to the end of the array - before init tab
+ if (compositionGroup.groupIsMerged === false || compositionGroup.groupIsMerged === undefined) {
// make parentTabContentTypeNames to an array so we can push values
- if (contentTypeGroup.parentTabContentTypeNames === null || contentTypeGroup.parentTabContentTypeNames === undefined) {
- contentTypeGroup.parentTabContentTypeNames = [];
+ if (compositionGroup.parentTabContentTypeNames === null || compositionGroup.parentTabContentTypeNames === undefined) {
+ compositionGroup.parentTabContentTypeNames = [];
}
// push name to array of merged composite content types
- contentTypeGroup.parentTabContentTypeNames.push(compositeContentType.name);
+ compositionGroup.parentTabContentTypeNames.push(compositeContentType.name);
// make parentTabContentTypes to an array so we can push values
- if (contentTypeGroup.parentTabContentTypes === null || contentTypeGroup.parentTabContentTypes === undefined) {
- contentTypeGroup.parentTabContentTypes = [];
+ if (compositionGroup.parentTabContentTypes === null || compositionGroup.parentTabContentTypes === undefined) {
+ compositionGroup.parentTabContentTypes = [];
}
// push id to array of merged composite content types
- contentTypeGroup.parentTabContentTypes.push(compositeContentType.id);
+ compositionGroup.parentTabContentTypes.push(compositeContentType.id);
- // get sort order from composition
- contentTypeGroup.sortOrder = compositionGroup.sortOrder;
+ // push group before placeholder tab
+ contentType.groups.unshift(compositionGroup);
- // splice group to the top of the array
- var contentTypeGroupCopy = angular.copy(contentTypeGroup);
- var index = contentType.groups.indexOf(contentTypeGroup);
- contentType.groups.splice(index, 1);
- contentType.groups.unshift(contentTypeGroupCopy);
+ }
- }
+ });
- });
+ // sort all groups by sortOrder property
+ contentType.groups = $filter('orderBy')(contentType.groups, 'sortOrder');
- // if group is not merged - push it to the end of the array - before init tab
- if (compositionGroup.groupIsMerged === false || compositionGroup.groupIsMerged === undefined) {
-
- // make parentTabContentTypeNames to an array so we can push values
- if (compositionGroup.parentTabContentTypeNames === null || compositionGroup.parentTabContentTypeNames === undefined) {
- compositionGroup.parentTabContentTypeNames = [];
- }
-
- // push name to array of merged composite content types
- compositionGroup.parentTabContentTypeNames.push(compositeContentType.name);
-
- // make parentTabContentTypes to an array so we can push values
- if (compositionGroup.parentTabContentTypes === null || compositionGroup.parentTabContentTypes === undefined) {
- compositionGroup.parentTabContentTypes = [];
- }
-
- // push id to array of merged composite content types
- compositionGroup.parentTabContentTypes.push(compositeContentType.id);
-
- // push group before placeholder tab
- contentType.groups.unshift(compositionGroup);
-
- }
-
- });
-
- // sort all groups by sortOrder property
- contentType.groups = $filter('orderBy')(contentType.groups, 'sortOrder');
-
- return contentType;
+ return contentType;
},
@@ -224,22 +224,22 @@ function contentTypeHelper(contentTypeResource, dataTypeResource, $filter, $inje
var groups = [];
- angular.forEach(contentType.groups, function(contentTypeGroup){
+ angular.forEach(contentType.groups, function (contentTypeGroup) {
- if( contentTypeGroup.tabState !== "init" ) {
+ if (contentTypeGroup.tabState !== "init") {
var idIndex = contentTypeGroup.parentTabContentTypes.indexOf(compositeContentType.id);
var nameIndex = contentTypeGroup.parentTabContentTypeNames.indexOf(compositeContentType.name);
var groupIndex = contentType.groups.indexOf(contentTypeGroup);
- if( idIndex !== -1 ) {
+ if (idIndex !== -1) {
var properties = [];
// remove all properties from composite content type
- angular.forEach(contentTypeGroup.properties, function(property){
- if(property.contentTypeId !== compositeContentType.id) {
+ angular.forEach(contentTypeGroup.properties, function (property) {
+ if (property.contentTypeId !== compositeContentType.id) {
properties.push(property);
}
});
@@ -252,22 +252,22 @@ function contentTypeHelper(contentTypeResource, dataTypeResource, $filter, $inje
contentTypeGroup.parentTabContentTypeNames.splice(nameIndex, 1);
// remove inherited state if there are no inherited properties
- if(contentTypeGroup.parentTabContentTypes.length === 0) {
+ if (contentTypeGroup.parentTabContentTypes.length === 0) {
contentTypeGroup.inherited = false;
}
// remove group if there are no properties left
- if(contentTypeGroup.properties.length > 1) {
+ if (contentTypeGroup.properties.length > 1) {
//contentType.groups.splice(groupIndex, 1);
groups.push(contentTypeGroup);
}
} else {
- groups.push(contentTypeGroup);
+ groups.push(contentTypeGroup);
}
} else {
- groups.push(contentTypeGroup);
+ groups.push(contentTypeGroup);
}
// update sort order on properties
@@ -281,67 +281,67 @@ function contentTypeHelper(contentTypeResource, dataTypeResource, $filter, $inje
updatePropertiesSortOrder: function (properties) {
- var sortOrder = 0;
+ var sortOrder = 0;
- angular.forEach(properties, function(property) {
- if( !property.inherited && property.propertyState !== "init") {
- property.sortOrder = sortOrder;
- }
- sortOrder++;
- });
+ angular.forEach(properties, function (property) {
+ if (!property.inherited && property.propertyState !== "init") {
+ property.sortOrder = sortOrder;
+ }
+ sortOrder++;
+ });
- return properties;
+ return properties;
},
- getTemplatePlaceholder: function() {
+ getTemplatePlaceholder: function () {
- var templatePlaceholder = {
- "name": "",
- "icon": "icon-layout",
- "alias": "templatePlaceholder",
- "placeholder": true
- };
+ var templatePlaceholder = {
+ "name": "",
+ "icon": "icon-layout",
+ "alias": "templatePlaceholder",
+ "placeholder": true
+ };
- return templatePlaceholder;
+ return templatePlaceholder;
},
- insertDefaultTemplatePlaceholder: function(defaultTemplate) {
+ insertDefaultTemplatePlaceholder: function (defaultTemplate) {
- // get template placeholder
- var templatePlaceholder = contentTypeHelperService.getTemplatePlaceholder();
+ // get template placeholder
+ var templatePlaceholder = contentTypeHelperService.getTemplatePlaceholder();
- // add as default template
- defaultTemplate = templatePlaceholder;
+ // add as default template
+ defaultTemplate = templatePlaceholder;
- return defaultTemplate;
+ return defaultTemplate;
},
- insertTemplatePlaceholder: function(array) {
+ insertTemplatePlaceholder: function (array) {
- // get template placeholder
- var templatePlaceholder = contentTypeHelperService.getTemplatePlaceholder();
+ // get template placeholder
+ var templatePlaceholder = contentTypeHelperService.getTemplatePlaceholder();
- // add as selected item
- array.push(templatePlaceholder);
+ // add as selected item
+ array.push(templatePlaceholder);
- return array;
+ return array;
- },
+ },
- insertChildNodePlaceholder: function (array, name, icon, id) {
+ insertChildNodePlaceholder: function (array, name, icon, id) {
- var placeholder = {
- "name": name,
- "icon": icon,
- "id": id
- };
+ var placeholder = {
+ "name": name,
+ "icon": icon,
+ "id": id
+ };
- array.push(placeholder);
+ array.push(placeholder);
- }
+ }
};
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 9c935086a0..538bd41ce0 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
@@ -164,14 +164,14 @@ When building a custom infinite editor view you can use the same components as a
"use strict";
function editorService(eventsService, keyboardService, $timeout) {
-
-
+
+
let editorsKeyboardShorcuts = [];
var editors = [];
var isEnabled = true;
var lastElementInFocus = null;
-
-
+
+
// events for backdrop
eventsService.on("appState.backdrop", function (name, args) {
if (args.show === true) {
@@ -180,7 +180,7 @@ When building a custom infinite editor view you can use the same components as a
focus();
}
});
-
+
/**
* @ngdoc method
@@ -205,7 +205,7 @@ When building a custom infinite editor view you can use the same components as a
function getNumberOfEditors() {
return editors.length;
};
-
+
/**
* @ngdoc method
* @name umbraco.services.editorService#blur
@@ -232,7 +232,7 @@ When building a custom infinite editor view you can use the same components as a
* Method to tell editors that they are gaining focus again.
*/
function focus() {
- if(isEnabled === false) {
+ if (isEnabled === false) {
/* keyboard shortcuts will be overwritten by the new infinite editor
so we need to store the shortcuts for the current editor so they can be rebound
when the infinite editor closes
@@ -241,7 +241,7 @@ When building a custom infinite editor view you can use the same components as a
isEnabled = true;
}
}
-
+
/**
* @ngdoc method
* @name umbraco.services.editorService#open
@@ -305,7 +305,7 @@ When building a custom infinite editor view you can use the same components as a
// delay required to map the properties to the correct editor due
// to another delay in the closing animation of the editor
- $timeout(function() {
+ $timeout(function () {
// rebind keyboard shortcuts for the new editor in focus
rebindKeyboardShortcuts();
@@ -651,7 +651,7 @@ When building a custom infinite editor view you can use the same components as a
editor.view = "views/mediatypes/edit.html";
open(editor);
}
-
+
/**
* @ngdoc method
* @name umbraco.services.editorService#memberTypeEditor
@@ -928,21 +928,21 @@ When building a custom infinite editor view you can use the same components as a
open(editor);
}
- /**
- * @ngdoc method
- * @name umbraco.services.editorService#memberPicker
- * @methodOf umbraco.services.editorService
- *
- * @description
- * Opens a member picker in infinite editing, the submit callback returns an array of selected items
- *
- * @param {Object} editor rendering options
- * @param {Boolean} editor.multiPicker Pick one or multiple items
- * @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.
- *
- * @returns {Object} editor object
- */
+ /**
+ * @ngdoc method
+ * @name umbraco.services.editorService#memberPicker
+ * @methodOf umbraco.services.editorService
+ *
+ * @description
+ * Opens a member picker in infinite editing, the submit callback returns an array of selected items
+ *
+ * @param {Object} editor rendering options
+ * @param {Boolean} editor.multiPicker Pick one or multiple items
+ * @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.
+ *
+ * @returns {Object} editor object
+ */
function memberPicker(editor) {
editor.view = "views/common/infiniteeditors/treepicker/treepicker.html";
if (!editor.size) editor.size = "small";
@@ -985,7 +985,7 @@ When building a custom infinite editor view you can use the same components as a
*
*/
function unbindKeyboardShortcuts() {
- const shortcuts = angular.copy(keyboardService.keyboardEvent);
+ const shortcuts = Utilities.copy(keyboardService.keyboardEvent);
editorsKeyboardShorcuts.push(shortcuts);
// unbind the current shortcuts because we only want to
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/events.service.js b/src/Umbraco.Web.UI.Client/src/common/services/events.service.js
index 51f63e6787..965ac3d635 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/events.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/events.service.js
@@ -1,7 +1,7 @@
/** Used to broadcast and listen for global events and allow the ability to add async listeners to the callbacks */
/*
- Core app events:
+ Core app events:
app.ready
app.authenticated
@@ -12,9 +12,9 @@
*/
function eventsService($q, $rootScope) {
-
+
return {
-
+
/** raise an event with a given name */
emit: function (name, args) {
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/filemanager.service.js b/src/Umbraco.Web.UI.Client/src/common/services/filemanager.service.js
index 41614a3bee..38aee3fc4a 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/filemanager.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/filemanager.service.js
@@ -27,10 +27,10 @@ function fileManager($rootScope) {
setFiles: function (args) {
//propertyAlias, files
- if (!angular.isString(args.propertyAlias)) {
+ if (!Utilities.isString(args.propertyAlias)) {
throw "args.propertyAlias must be a non empty string";
}
- if (!angular.isObject(args.files)) {
+ if (!Utilities.isObject(args.files)) {
throw "args.files must be an object";
}
@@ -39,18 +39,22 @@ function fileManager($rootScope) {
args.culture = null;
}
+ if (!args.segment) {
+ args.segment = null;
+ }
+
var metaData = [];
- if (angular.isArray(args.metaData)) {
+ if (Utilities.isArray(args.metaData)) {
metaData = args.metaData;
}
- //this will clear the files for the current property/culture and then add the new ones for the current property
+ //this will clear the files for the current property/culture/segment and then add the new ones for the current property
fileCollection = _.reject(fileCollection, function (item) {
- return item.alias === args.propertyAlias && (!args.culture || args.culture === item.culture);
+ return item.alias === args.propertyAlias && (!args.culture || args.culture === item.culture) && (!args.segment || args.segment === item.segment);
});
for (var i = 0; i < args.files.length; i++) {
//save the file object to the files collection
- fileCollection.push({ alias: args.propertyAlias, file: args.files[i], culture: args.culture, metaData: metaData });
+ fileCollection.push({ alias: args.propertyAlias, file: args.files[i], culture: args.culture, segment: args.segment, metaData: metaData });
}
},
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js
index 0555318bae..90fbd76ec9 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js
@@ -83,7 +83,7 @@ function formHelper(angularHelper, serverValidationManager, notificationsService
if (!args || !args.notifications) {
return false;
}
- if (angular.isArray(args.notifications)) {
+ if (Utilities.isArray(args.notifications)) {
for (var i = 0; i < args.notifications.length; i++) {
notificationsService.showNotification(args.notifications[i]);
}
@@ -159,9 +159,16 @@ function formHelper(angularHelper, serverValidationManager, notificationsService
//the alias in model state can be in dot notation which indicates
// * the first part is the content property alias
// * the second part is the field to which the valiation msg is associated with
- //There will always be at least 3 parts for content properties since all model errors for properties are prefixed with "_Properties"
+ //There will always be at least 4 parts for content properties since all model errors for properties are prefixed with "_Properties"
//If it is not prefixed with "_Properties" that means the error is for a field of the object directly.
+ // Example: "_Properties.headerImage.en-US.mySegment.myField"
+ // * it's for a property since it has a _Properties prefix
+ // * it's for the headerImage property type
+ // * it's for the en-US culture
+ // * it's for the mySegment segment
+ // * it's for the myField html field (optional)
+
var parts = e.split(".");
//Check if this is for content properties - specific to content/media/member editors because those are special
@@ -179,16 +186,23 @@ function formHelper(angularHelper, serverValidationManager, notificationsService
}
}
- //if it contains 3 '.' then we will wire it up to a property's html field
+ var segment = null;
if (parts.length > 3) {
- //add an error with a reference to the field for which the validation belongs too
- serverValidationManager.addPropertyError(propertyAlias, culture, parts[3], modelState[e][0]);
+ segment = parts[3];
+ //special check in case the string is formatted this way
+ if (segment === "null") {
+ segment = null;
+ }
}
- else {
- //add a generic error for the property, no reference to a specific html field
- serverValidationManager.addPropertyError(propertyAlias, culture, "", modelState[e][0]);
+
+ var htmlFieldReference = "";
+ if (parts.length > 4) {
+ htmlFieldReference = parts[4] || "";
}
+ // add a generic error for the property
+ serverValidationManager.addPropertyError(propertyAlias, culture, htmlFieldReference, modelState[e][0], segment);
+
} else {
//Everthing else is just a 'Field'... the field name could contain any level of 'parts' though, for example:
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js
index 20d014ab0f..28156e70c3 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js
@@ -332,14 +332,14 @@
selection.length = 0;
- if (angular.isArray(items)) {
+ if (Utilities.isArray(items)) {
for (i = 0; items.length > i; i++) {
var item = items[i];
item.selected = false;
}
}
- if(angular.isArray(folders)) {
+ if(Utilities.isArray(folders)) {
for (i = 0; folders.length > i; i++) {
var folder = folders[i];
folder.selected = false;
@@ -366,7 +366,7 @@
var checkbox = $event.target;
var clearSelection = false;
- if (!angular.isArray(items)) {
+ if (!Utilities.isArray(items)) {
return;
}
@@ -413,7 +413,7 @@
function selectAllItemsToggle(items, selection) {
- if (!angular.isArray(items)) {
+ if (!Utilities.isArray(items)) {
return;
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/macro.service.js b/src/Umbraco.Web.UI.Client/src/common/services/macro.service.js
index a91f9d51e4..5b79b9c327 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/macro.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/macro.service.js
@@ -62,12 +62,12 @@ function macroService() {
val = val ? val : "";
//need to detect if the val is a string or an object
var keyVal;
- if (angular.isString(val)) {
+ if (Utilities.isString(val)) {
keyVal = key + "=\"" + (val ? val : "") + "\" ";
}
else {
//if it's not a string we'll send it through the json serializer
- var json = angular.toJson(val);
+ var json = Utilities.toJson(val);
//then we need to url encode it so that it's safe
var encoded = encodeURIComponent(json);
keyVal = key + "=\"" + encoded + "\" ";
@@ -142,7 +142,7 @@ function macroService() {
if (item.value !== null && item.value !== undefined && !_.isString(item.value)) {
try {
- val = angular.toJson(val);
+ val = Utilities.toJson(val);
}
catch (e) {
// not json
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js
index 2271f891ce..ce2a18c3c0 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js
@@ -45,7 +45,7 @@ function mediaHelper(umbRequestHelper, $log) {
//this performs a simple check to see if we have a media file as value
//it doesnt catch everything, but better then nothing
- if (angular.isString(item.value) && item.value.indexOf(mediaRoot) === 0) {
+ if (Utilities.isString(item.value) && item.value.indexOf(mediaRoot) === 0) {
return true;
}
@@ -143,7 +143,7 @@ function mediaHelper(umbRequestHelper, $log) {
*/
resolveFileFromEntity: function (mediaEntity, thumbnail) {
- var mediaPath = angular.isObject(mediaEntity.metaData) ? mediaEntity.metaData.MediaPath : null;
+ var mediaPath = Utilities.isObject(mediaEntity.metaData) ? mediaEntity.metaData.MediaPath : null;
if (!mediaPath) {
//don't throw since this image legitimately might not contain a media path, but output a warning
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js
index ab9cfb63d2..da784a1f9e 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js
@@ -26,60 +26,60 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
navReadyPromise.resolve(mainTreeApi);
});
-
+
//A list of query strings defined that when changed will not cause a reload of the route
- var nonRoutingQueryStrings = ["mculture", "cculture", "lq", "sr"];
+ var nonRoutingQueryStrings = ["mculture", "cculture", "csegment", "lq", "sr"];
var retainedQueryStrings = ["mculture"];
-
+
function setMode(mode) {
switch (mode) {
- case 'tree':
- appState.setGlobalState("navMode", "tree");
- appState.setGlobalState("showNavigation", true);
- appState.setMenuState("showMenu", false);
- appState.setMenuState("showMenuDialog", false);
- appState.setGlobalState("stickyNavigation", false);
- appState.setGlobalState("showTray", false);
- break;
- case 'menu':
- appState.setGlobalState("navMode", "menu");
- appState.setGlobalState("showNavigation", true);
- appState.setMenuState("showMenu", true);
- appState.setMenuState("showMenuDialog", false);
- appState.setGlobalState("stickyNavigation", true);
- break;
- case 'dialog':
- appState.setGlobalState("navMode", "dialog");
- appState.setGlobalState("stickyNavigation", true);
- appState.setGlobalState("showNavigation", true);
- appState.setMenuState("showMenu", false);
- appState.setMenuState("showMenuDialog", true);
- appState.setMenuState("allowHideMenuDialog", true);
- break;
- case 'search':
- appState.setGlobalState("navMode", "search");
- appState.setGlobalState("stickyNavigation", false);
- appState.setGlobalState("showNavigation", true);
- appState.setMenuState("showMenu", false);
- appState.setSectionState("showSearchResults", true);
- appState.setMenuState("showMenuDialog", false);
- break;
- default:
- appState.setGlobalState("navMode", "default");
- appState.setMenuState("showMenu", false);
- appState.setMenuState("showMenuDialog", false);
- appState.setMenuState("allowHideMenuDialog", true);
- appState.setSectionState("showSearchResults", false);
- appState.setGlobalState("stickyNavigation", false);
- appState.setGlobalState("showTray", false);
- appState.setMenuState("currentNode", null);
+ case 'tree':
+ appState.setGlobalState("navMode", "tree");
+ appState.setGlobalState("showNavigation", true);
+ appState.setMenuState("showMenu", false);
+ appState.setMenuState("showMenuDialog", false);
+ appState.setGlobalState("stickyNavigation", false);
+ appState.setGlobalState("showTray", false);
+ break;
+ case 'menu':
+ appState.setGlobalState("navMode", "menu");
+ appState.setGlobalState("showNavigation", true);
+ appState.setMenuState("showMenu", true);
+ appState.setMenuState("showMenuDialog", false);
+ appState.setGlobalState("stickyNavigation", true);
+ break;
+ case 'dialog':
+ appState.setGlobalState("navMode", "dialog");
+ appState.setGlobalState("stickyNavigation", true);
+ appState.setGlobalState("showNavigation", true);
+ appState.setMenuState("showMenu", false);
+ appState.setMenuState("showMenuDialog", true);
+ appState.setMenuState("allowHideMenuDialog", true);
+ break;
+ case 'search':
+ appState.setGlobalState("navMode", "search");
+ appState.setGlobalState("stickyNavigation", false);
+ appState.setGlobalState("showNavigation", true);
+ appState.setMenuState("showMenu", false);
+ appState.setSectionState("showSearchResults", true);
+ appState.setMenuState("showMenuDialog", false);
+ break;
+ default:
+ appState.setGlobalState("navMode", "default");
+ appState.setMenuState("showMenu", false);
+ appState.setMenuState("showMenuDialog", false);
+ appState.setMenuState("allowHideMenuDialog", true);
+ appState.setSectionState("showSearchResults", false);
+ appState.setGlobalState("stickyNavigation", false);
+ appState.setGlobalState("showTray", false);
+ appState.setMenuState("currentNode", null);
- if (appState.getGlobalState("isTablet") === true) {
- appState.setGlobalState("showNavigation", false);
- }
+ if (appState.getGlobalState("isTablet") === true) {
+ appState.setGlobalState("showNavigation", false);
+ }
- break;
+ break;
}
}
@@ -88,7 +88,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
* @param {any} requestPath
*/
function pathToRouteParts(requestPath) {
- if (!angular.isString(requestPath)) {
+ if (!Utilities.isString(requestPath)) {
throw "The value for requestPath is not a string";
}
var pathAndQuery = requestPath.split("#")[1];
@@ -114,7 +114,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
}
var service = {
-
+
/**
* @ngdoc method
* @name umbraco.services.navigationService#isRouteChangingNavigation
@@ -130,11 +130,11 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
*/
isRouteChangingNavigation: function (currUrlParams, nextUrlParams) {
- if (angular.isString(currUrlParams)) {
+ if (Utilities.isString(currUrlParams)) {
currUrlParams = pathToRouteParts(currUrlParams);
}
- if (angular.isString(nextUrlParams)) {
+ if (Utilities.isString(nextUrlParams)) {
nextUrlParams = pathToRouteParts(nextUrlParams);
}
@@ -151,7 +151,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
var nextRoutingKeys = _.difference(_.keys(nextUrlParams), nonRoutingQueryStrings);
var diff1 = _.difference(currRoutingKeys, nextRoutingKeys);
var diff2 = _.difference(nextRoutingKeys, currRoutingKeys);
-
+
//if the routing parameter keys are the same, we'll compare their values to see if any have changed and if so then the routing will be allowed.
if (diff1.length === 0 && diff2.length === 0) {
var partsChanged = 0;
@@ -223,7 +223,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
* @param {Object} nextRouteParams The next route parameters
*/
retainQueryStrings: function (currRouteParams, nextRouteParams) {
- var toRetain = angular.copy(nextRouteParams);
+ var toRetain = Utilities.copy(nextRouteParams);
var updated = false;
_.each(retainedQueryStrings, function (r) {
@@ -260,7 +260,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
* and load the dashboard related to the section
* @param {string} sectionAlias The alias of the section
*/
- changeSection: function(sectionAlias, force) {
+ changeSection: function (sectionAlias, force) {
setMode("default-opensection");
if (force && appState.getSectionState("currentSection") === sectionAlias) {
@@ -360,19 +360,19 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
TODO: Delete this if not required
*/
- _syncPath: function(path, forceReload) {
+ _syncPath: function (path, forceReload) {
return navReadyPromise.promise.then(function () {
return mainTreeApi.syncTree({ path: path, forceReload: forceReload });
});
},
-
- reloadNode: function(node) {
+
+ reloadNode: function (node) {
return navReadyPromise.promise.then(function () {
return mainTreeApi.reloadNode(node);
});
},
-
- reloadSection: function(sectionAlias) {
+
+ reloadSection: function (sectionAlias) {
return navReadyPromise.promise.then(function () {
treeService.clearCache({ section: sectionAlias });
return mainTreeApi.load(sectionAlias);
@@ -387,11 +387,11 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
* @description
* Hides the tree by hiding the containing dom element
*/
- hideTree: function() {
+ hideTree: function () {
if (appState.getGlobalState("isTablet") === true && !appState.getGlobalState("stickyNavigation")) {
//reset it to whatever is in the url
- appState.setSectionState("currentSection", $routeParams.section);
+ appState.setSectionState("currentSection", $routeParams.section);
setMode("default-hidesectiontree");
}
@@ -409,19 +409,19 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
*
* @param {Event} event the click event triggering the method, passed from the DOM element
*/
- showMenu: function(args) {
-
+ showMenu: function (args) {
+
var self = this;
return treeService.getMenu({ treeNode: args.node })
- .then(function(data) {
+ .then(function (data) {
//check for a default
//NOTE: event will be undefined when a call to hideDialog is made so it won't re-load the default again.
// but perhaps there's a better way to deal with with an additional parameter in the args ? it works though.
if (data.defaultAlias && !args.skipDefault) {
- var found = _.find(data.menuItems, function(item) {
+ var found = _.find(data.menuItems, function (item) {
return item.alias = data.defaultAlias;
});
@@ -450,7 +450,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
return $q.resolve();
});
-
+
},
/**
@@ -461,7 +461,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
* @description
* Hides the menu by hiding the containing dom element
*/
- hideMenu: function() {
+ hideMenu: function () {
//SD: Would we ever want to access the last action'd node instead of clearing it here?
appState.setMenuState("currentNode", null);
appState.setMenuState("menuActions", []);
@@ -483,14 +483,14 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
appState.setMenuState("currentNode", node);
- if (action.metaData && action.metaData["actionRoute"] && angular.isString(action.metaData["actionRoute"])) {
+ if (action.metaData && action.metaData["actionRoute"] && Utilities.isString(action.metaData["actionRoute"])) {
//first check if the menu item simply navigates to a route
var parts = action.metaData["actionRoute"].split("?");
$location.path(parts[0]).search(parts.length > 1 ? parts[1] : "");
this.hideNavigation();
return;
}
- else if (action.metaData && action.metaData["jsAction"] && angular.isString(action.metaData["jsAction"])) {
+ else if (action.metaData && action.metaData["jsAction"] && Utilities.isString(action.metaData["jsAction"])) {
//we'll try to get the jsAction from the injector
var menuAction = action.metaData["jsAction"].split('.');
@@ -532,7 +532,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
});
}
},
-
+
/**
* @ngdoc method
@@ -553,7 +553,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
* @param {Scope} args.scope current scope passed to the dialog
* @param {Object} args.action the clicked action containing `name` and `alias`
*/
- showDialog: function(args) {
+ showDialog: function (args) {
if (!args) {
throw "showDialog is missing the args parameter";
@@ -578,20 +578,20 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
if (args.action.metaData["actionView"]) {
templateUrl = args.action.metaData["actionView"];
}
- else {
+ else {
var treeAlias = treeService.getTreeAlias(args.node);
if (!treeAlias) {
throw "Could not get tree alias for node " + args.node.id;
- }
+ }
templateUrl = this.getTreeTemplateUrl(treeAlias, args.action.alias);
}
setMode("dialog");
- if(templateUrl) {
+ if (templateUrl) {
appState.setMenuState("dialogTemplateUrl", templateUrl);
}
-
+
},
/**
* @ngdoc method
@@ -607,7 +607,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
* we will also check for a 'packageName' for the current tree, if it exists then the convention will be:
* for example: /App_Plugins/{mypackage}/backoffice/{treetype}/create.html
*/
- getTreeTemplateUrl: function(treeAlias, action) {
+ getTreeTemplateUrl: function (treeAlias, action) {
var packageTreeFolder = treeService.getTreePackageFolder(treeAlias);
if (packageTreeFolder) {
return Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath +
@@ -661,7 +661,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
* @description
* shows the search pane
*/
- showSearch: function() {
+ showSearch: function () {
setMode("search");
},
/**
@@ -672,7 +672,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
* @description
* hides the search pane
*/
- hideSearch: function() {
+ hideSearch: function () {
setMode("default-hidesearch");
},
/**
@@ -683,7 +683,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService
* @description
* hides any open navigation panes and resets the tree, actions and the currently selected node
*/
- hideNavigation: function() {
+ hideNavigation: function () {
appState.setMenuState("menuActions", []);
setMode("default");
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/notifications.service.js b/src/Umbraco.Web.UI.Client/src/common/services/notifications.service.js
index e5701b9de0..196e0e3baa 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/notifications.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/notifications.service.js
@@ -245,7 +245,7 @@ angular.module('umbraco.services')
* @param {Int} index index where the notication should be removed from
*/
remove: function (index) {
- if(angular.isObject(index)){
+ if (Utilities.isObject(index)){
var i = nArray.indexOf(index);
angularHelper.safeApply($rootScope, function() {
nArray.splice(i, 1);
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/servervalidationmgr.service.js b/src/Umbraco.Web.UI.Client/src/common/services/servervalidationmgr.service.js
index b9bfa51122..718e44d66e 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/servervalidationmgr.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/servervalidationmgr.service.js
@@ -13,19 +13,20 @@ function serverValidationManager($timeout) {
var callbacks = [];
/** calls the callback specified with the errors specified, used internally */
- function executeCallback(self, errorsForCallback, callback, culture) {
+ function executeCallback(self, errorsForCallback, callback, culture, segment) {
callback.apply(self, [
false, // pass in a value indicating it is invalid
errorsForCallback, // pass in the errors for this item
self.items, // pass in all errors in total
- culture // pass the culture that we are listing for.
+ culture, // pass the culture that we are listing for.
+ segment // pass the segment that we are listing for.
]
);
}
function getFieldErrors(self, fieldName) {
- if (!angular.isString(fieldName)) {
+ if (!Utilities.isString(fieldName)) {
throw "fieldName must be a string";
}
@@ -35,33 +36,40 @@ function serverValidationManager($timeout) {
});
}
- function getPropertyErrors(self, propertyAlias, culture, fieldName) {
- if (!angular.isString(propertyAlias)) {
+
+ function getPropertyErrors(self, propertyAlias, culture, segment, fieldName) {
+ if (!Utilities.isString(propertyAlias)) {
throw "propertyAlias must be a string";
}
- if (fieldName && !angular.isString(fieldName)) {
+ if (fieldName && !Utilities.isString(fieldName)) {
throw "fieldName must be a string";
}
if (!culture) {
culture = "invariant";
}
+ if (!segment) {
+ segment = null;
+ }
//find all errors for this property
return _.filter(self.items, function (item) {
- return (item.propertyAlias === propertyAlias && item.culture === culture && (item.fieldName === fieldName || (fieldName === undefined || fieldName === "")));
+ return (item.propertyAlias === propertyAlias && item.culture === culture && item.segment === segment && (item.fieldName === fieldName || (fieldName === undefined || fieldName === "")));
});
}
- function getCultureErrors(self, culture) {
+ function getVariantErrors(self, culture, segment) {
if (!culture) {
culture = "invariant";
}
+ if (!segment) {
+ segment = null;
+ }
//find all errors for this property
return _.filter(self.items, function (item) {
- return (item.culture === culture);
+ return (item.culture === culture && item.segment === segment);
});
}
@@ -71,21 +79,21 @@ function serverValidationManager($timeout) {
//its a field error callback
var fieldErrors = getFieldErrors(self, callbacks[cb].fieldName);
if (fieldErrors.length > 0) {
- executeCallback(self, fieldErrors, callbacks[cb].callback, callbacks[cb].culture);
+ executeCallback(self, fieldErrors, callbacks[cb].callback, callbacks[cb].culture, callbacks[cb].segment);
}
}
else if (callbacks[cb].propertyAlias != null) {
//its a property error
- var propErrors = getPropertyErrors(self, callbacks[cb].propertyAlias, callbacks[cb].culture, callbacks[cb].fieldName);
+ var propErrors = getPropertyErrors(self, callbacks[cb].propertyAlias, callbacks[cb].culture, callbacks[cb].segment, callbacks[cb].fieldName);
if (propErrors.length > 0) {
- executeCallback(self, propErrors, callbacks[cb].callback, callbacks[cb].culture);
+ executeCallback(self, propErrors, callbacks[cb].callback, callbacks[cb].culture, callbacks[cb].segment);
}
}
else {
- //its a culture error
- var cultureErrors = getCultureErrors(self, callbacks[cb].culture);
- if (cultureErrors.length > 0) {
- executeCallback(self, cultureErrors, callbacks[cb].callback, callbacks[cb].culture);
+ //its a variant error
+ var variantErrors = getVariantErrors(self, callbacks[cb].culture, callbacks[cb].segment);
+ if (variantErrors.length > 0) {
+ executeCallback(self, variantErrors, callbacks[cb].callback, callbacks[cb].culture, callbacks[cb].segment);
}
}
}
@@ -150,20 +158,27 @@ function serverValidationManager($timeout) {
* field alias to listen for.
* If propertyAlias is null, then this subscription is for a field property (not a user defined property).
*/
- subscribe: function (propertyAlias, culture, fieldName, callback) {
+ subscribe: function (propertyAlias, culture, fieldName, callback, segment) {
if (!callback) {
return;
}
var id = String.CreateGuid();
+
+ //normalize culture to "invariant"
if (!culture) {
culture = "invariant";
}
+ //normalize segment to null
+ if (!segment) {
+ segment = null;
+ }
if (propertyAlias === null) {
callbacks.push({
propertyAlias: null,
culture: culture,
+ segment: segment,
fieldName: fieldName,
callback: callback,
id: id
@@ -175,6 +190,7 @@ function serverValidationManager($timeout) {
callbacks.push({
propertyAlias: propertyAlias,
culture: culture,
+ segment: segment,
fieldName: fieldName,
callback: callback,
id: id
@@ -199,25 +215,29 @@ function serverValidationManager($timeout) {
* @param {} fieldName
* @returns {}
*/
- unsubscribe: function (propertyAlias, culture, fieldName) {
+ unsubscribe: function (propertyAlias, culture, fieldName, segment) {
- //normalize culture to null
+ //normalize culture to "invariant"
if (!culture) {
culture = "invariant";
}
+ //normalize segment to null
+ if (!segment) {
+ segment = null;
+ }
if (propertyAlias === null) {
//remove all callbacks for the content field
callbacks = _.reject(callbacks, function (item) {
- return item.propertyAlias === null && item.culture === culture && item.fieldName === fieldName;
+ return item.propertyAlias === null && item.culture === culture && item.segment === segment && item.fieldName === fieldName;
});
}
else if (propertyAlias !== undefined) {
//remove all callbacks for the content property
callbacks = _.reject(callbacks, function (item) {
- return item.propertyAlias === propertyAlias && item.culture === culture &&
+ return item.propertyAlias === propertyAlias && item.culture === culture && item.segment === segment &&
(item.fieldName === fieldName ||
((item.fieldName === undefined || item.fieldName === "") && (fieldName === undefined || fieldName === "")));
});
@@ -236,16 +256,20 @@ function serverValidationManager($timeout) {
* This will always return any callbacks registered for just the property (i.e. field name is empty) and for ones with an
* explicit field name set.
*/
- getPropertyCallbacks: function (propertyAlias, culture, fieldName) {
+ getPropertyCallbacks: function (propertyAlias, culture, fieldName, segment) {
- //normalize culture to null
+ //normalize culture to "invariant"
if (!culture) {
culture = "invariant";
}
+ //normalize segment to null
+ if (!segment) {
+ segment = null;
+ }
var found = _.filter(callbacks, function (item) {
//returns any callback that have been registered directly against the field and for only the property
- return (item.propertyAlias === propertyAlias && item.culture === culture && (item.fieldName === fieldName || (item.fieldName === undefined || item.fieldName === "")));
+ return (item.propertyAlias === propertyAlias && item.culture === culture && item.segment === segment && (item.fieldName === fieldName || (item.fieldName === undefined || item.fieldName === "")));
});
return found;
},
@@ -262,7 +286,7 @@ function serverValidationManager($timeout) {
getFieldCallbacks: function (fieldName) {
var found = _.filter(callbacks, function (item) {
//returns any callback that have been registered directly against the field
- return (item.propertyAlias === null && item.culture === "invariant" && item.fieldName === fieldName);
+ return (item.propertyAlias === null && item.culture === "invariant" && item.segment === null && item.fieldName === fieldName);
});
return found;
},
@@ -274,12 +298,29 @@ function serverValidationManager($timeout) {
* @function
*
* @description
- * Gets all callbacks that has been registered using the subscribe method for the culture.
+ * Gets all callbacks that has been registered using the subscribe method for the culture. Not including segments.
*/
getCultureCallbacks: function (culture) {
var found = _.filter(callbacks, function (item) {
//returns any callback that have been registered directly/ONLY against the culture
- return (item.culture === culture && item.propertyAlias === null && item.fieldName === null);
+ return (item.culture === culture && item.segment === null && item.propertyAlias === null && item.fieldName === null);
+ });
+ return found;
+ },
+
+ /**
+ * @ngdoc function
+ * @name getVariantCallbacks
+ * @methodOf umbraco.services.serverValidationManager
+ * @function
+ *
+ * @description
+ * Gets all callbacks that has been registered using the subscribe method for the culture and segment.
+ */
+ getVariantCallbacks: function (culture, segment) {
+ var found = _.filter(callbacks, function (item) {
+ //returns any callback that have been registered directly against the given culture and given segment.
+ return (item.culture === culture && item.segment === segment && item.propertyAlias === null && item.fieldName === null);
});
return found;
},
@@ -303,6 +344,7 @@ function serverValidationManager($timeout) {
this.items.push({
propertyAlias: null,
culture: "invariant",
+ segment: null,
fieldName: fieldName,
errorMsg: errorMsg
});
@@ -314,7 +356,7 @@ function serverValidationManager($timeout) {
var cbs = this.getFieldCallbacks(fieldName);
//call each callback for this error
for (var cb in cbs) {
- executeCallback(this, errorsForCallback, cbs[cb].callback, null);
+ executeCallback(this, errorsForCallback, cbs[cb].callback, null, null);
}
},
@@ -327,7 +369,7 @@ function serverValidationManager($timeout) {
* @description
* Adds an error message for the content property
*/
- addPropertyError: function (propertyAlias, culture, fieldName, errorMsg) {
+ addPropertyError: function (propertyAlias, culture, fieldName, errorMsg, segment) {
if (!propertyAlias) {
return;
}
@@ -336,31 +378,36 @@ function serverValidationManager($timeout) {
if (!culture) {
culture = "invariant";
}
+ //normalize segment to null
+ if (!segment) {
+ segment = null;
+ }
//only add the item if it doesn't exist
- if (!this.hasPropertyError(propertyAlias, culture, fieldName)) {
+ if (!this.hasPropertyError(propertyAlias, culture, fieldName, segment)) {
this.items.push({
propertyAlias: propertyAlias,
culture: culture,
+ segment: segment,
fieldName: fieldName,
errorMsg: errorMsg
});
}
//find all errors for this item
- var errorsForCallback = getPropertyErrors(this, propertyAlias, culture, fieldName);
+ var errorsForCallback = getPropertyErrors(this, propertyAlias, culture, segment, fieldName);
//we should now call all of the call backs registered for this error
- var cbs = this.getPropertyCallbacks(propertyAlias, culture, fieldName);
+ var cbs = this.getPropertyCallbacks(propertyAlias, culture, fieldName, segment);
//call each callback for this error
for (var cb in cbs) {
- executeCallback(this, errorsForCallback, cbs[cb].callback, culture);
+ executeCallback(this, errorsForCallback, cbs[cb].callback, culture, segment);
}
- //execute culture specific callbacks here too when a propery error is added
- var cultureCbs = this.getCultureCallbacks(culture);
+ //execute variant specific callbacks here too when a propery error is added
+ var variantCbs = this.getVariantCallbacks(culture, segment);
//call each callback for this error
- for (var cb in cultureCbs) {
- executeCallback(this, errorsForCallback, cultureCbs[cb].callback, culture);
+ for (var cb in variantCbs) {
+ executeCallback(this, errorsForCallback, variantCbs[cb].callback, culture, segment);
}
},
@@ -373,7 +420,7 @@ function serverValidationManager($timeout) {
* @description
* Removes an error message for the content property
*/
- removePropertyError: function (propertyAlias, culture, fieldName) {
+ removePropertyError: function (propertyAlias, culture, fieldName, segment) {
if (!propertyAlias) {
return;
@@ -383,10 +430,14 @@ function serverValidationManager($timeout) {
if (!culture) {
culture = "invariant";
}
+ //normalize segment to null
+ if (!segment) {
+ segment = null;
+ }
//remove the item
this.items = _.reject(this.items, function (item) {
- return (item.propertyAlias === propertyAlias && item.culture === culture && (item.fieldName === fieldName || (fieldName === undefined || fieldName === "")));
+ return (item.propertyAlias === propertyAlias && item.culture === culture && item.segment === segment && (item.fieldName === fieldName || (fieldName === undefined || fieldName === "")));
});
},
@@ -405,7 +456,10 @@ function serverValidationManager($timeout) {
callbacks[cb].callback.apply(this, [
true, //pass in a value indicating it is VALID
[], //pass in empty collection
- []]); //pass in empty collection
+ [],
+ null,
+ null]
+ );
}
},
@@ -431,16 +485,20 @@ function serverValidationManager($timeout) {
* @description
* Gets the error message for the content property
*/
- getPropertyError: function (propertyAlias, culture, fieldName) {
+ getPropertyError: function (propertyAlias, culture, fieldName, segment) {
- //normalize culture to null
+ //normalize culture to "invariant"
if (!culture) {
culture = "invariant";
}
+ //normalize segment to null
+ if (!segment) {
+ segment = null;
+ }
var err = _.find(this.items, function (item) {
//return true if the property alias matches and if an empty field name is specified or the field name matches
- return (item.propertyAlias === propertyAlias && item.culture === culture && (item.fieldName === fieldName || (fieldName === undefined || fieldName === "")));
+ return (item.propertyAlias === propertyAlias && item.culture === culture && item.segment === segment && (item.fieldName === fieldName || (fieldName === undefined || fieldName === "")));
});
return err;
},
@@ -457,7 +515,7 @@ function serverValidationManager($timeout) {
getFieldError: function (fieldName) {
var err = _.find(this.items, function (item) {
//return true if the property alias matches and if an empty field name is specified or the field name matches
- return (item.propertyAlias === null && item.culture === "invariant" && item.fieldName === fieldName);
+ return (item.propertyAlias === null && item.culture === "invariant" && item.segment === null && item.fieldName === fieldName);
});
return err;
},
@@ -471,16 +529,20 @@ function serverValidationManager($timeout) {
* @description
* Checks if the content property + culture + field name combo has an error
*/
- hasPropertyError: function (propertyAlias, culture, fieldName) {
+ hasPropertyError: function (propertyAlias, culture, fieldName, segment) {
//normalize culture to null
if (!culture) {
culture = "invariant";
}
+ //normalize segment to null
+ if (!segment) {
+ segment = null;
+ }
var err = _.find(this.items, function (item) {
//return true if the property alias matches and if an empty field name is specified or the field name matches
- return (item.propertyAlias === propertyAlias && item.culture === culture && (item.fieldName === fieldName || (fieldName === undefined || fieldName === "")));
+ return (item.propertyAlias === propertyAlias && item.culture === culture && item.segment === segment && (item.fieldName === fieldName || (fieldName === undefined || fieldName === "")));
});
return err ? true : false;
},
@@ -497,12 +559,11 @@ function serverValidationManager($timeout) {
hasFieldError: function (fieldName) {
var err = _.find(this.items, function (item) {
//return true if the property alias matches and if an empty field name is specified or the field name matches
- return (item.propertyAlias === null && item.culture === "invariant" && item.fieldName === fieldName);
+ return (item.propertyAlias === null && item.culture === "invariant" && item.segment === null && item.fieldName === fieldName);
});
return err ? true : false;
},
-
/**
* @ngdoc function
* @name hasCultureError
@@ -513,14 +574,40 @@ function serverValidationManager($timeout) {
* Checks if the given culture has an error
*/
hasCultureError: function (culture) {
-
- //normalize culture to null
+
+ //normalize culture to "invariant"
if (!culture) {
culture = "invariant";
}
+
+ var err = _.find(this.items, function (item) {
+ return (item.culture === culture && item.segment === null);
+ });
+ return err ? true : false;
+ },
+
+ /**
+ * @ngdoc function
+ * @name hasVariantError
+ * @methodOf umbraco.services.serverValidationManager
+ * @function
+ *
+ * @description
+ * Checks if the given culture has an error
+ */
+ hasVariantError: function (culture, segment) {
+
+ //normalize culture to "invariant"
+ if (!culture) {
+ culture = "invariant";
+ }
+ //normalize segment to null
+ if (!segment) {
+ segment = null;
+ }
var err = _.find(this.items, function (item) {
- return item.culture === culture;
+ return (item.culture === culture && item.segment === segment);
});
return err ? true : false;
},
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 d2b91a3707..66f0b110bf 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
@@ -480,7 +480,7 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s
//now we need to check if this custom config key is defined in our baseline, if it is we don't want to
//overwrite the baseline config item if it is an array, we want to concat the items in the array, otherwise
//if it's an object it will overwrite the baseline
- if (angular.isArray(config[i]) && angular.isArray(tinyMceConfig.customConfig[i])) {
+ if (Utilities.isArray(config[i]) && Utilities.isArray(tinyMceConfig.customConfig[i])) {
//concat it and below this concat'd array will overwrite the baseline in angular.extend
tinyMceConfig.customConfig[i] = config[i].concat(tinyMceConfig.customConfig[i]);
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tour.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tour.service.js
index 8fcab445b3..4166725c39 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/tour.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/tour.service.js
@@ -9,7 +9,7 @@
'use strict';
function tourService(eventsService, currentUserResource, $q, tourResource) {
-
+
var tours = [];
var currentTour = null;
@@ -18,14 +18,16 @@
*/
function registerAllTours() {
tours = [];
- return tourResource.getTours().then(function(tourFiles) {
- angular.forEach(tourFiles, function (tourFile) {
- angular.forEach(tourFile.tours, function(newTour) {
+ return tourResource.getTours().then(function (tourFiles) {
+ Utilities.forEach(tourFiles, tourFile => {
+
+ Utilities.forEach(tourFile.tours, newTour => {
validateTour(newTour);
validateTourRegistration(newTour);
- tours.push(newTour);
+ tours.push(newTour);
});
});
+
eventsService.emit("appState.tour.updatedTours", tours);
});
}
@@ -74,7 +76,7 @@
tour.disabled = true;
currentUserResource
.saveTourStatus({ alias: tour.alias, disabled: tour.disabled, completed: tour.completed }).then(
- function() {
+ function () {
eventsService.emit("appState.tour.end", tour);
currentTour = null;
deferred.resolve(tour);
@@ -96,7 +98,7 @@
tour.completed = true;
currentUserResource
.saveTourStatus({ alias: tour.alias, disabled: tour.disabled, completed: tour.completed }).then(
- function() {
+ function () {
eventsService.emit("appState.tour.complete", tour);
currentTour = null;
deferred.resolve(tour);
@@ -130,10 +132,10 @@
function getGroupedTours() {
var deferred = $q.defer();
var tours = getTours();
- setTourStatuses(tours).then(function() {
+ setTourStatuses(tours).then(function () {
var groupedTours = [];
tours.forEach(function (item) {
-
+
if (item.contentType === null || item.contentType === '') {
var groupExists = false;
var newGroup = {
@@ -149,9 +151,9 @@
}
groupExists = true;
- if(item.hidden === false){
- group.tours.push(item);
- }
+ if (item.hidden === false) {
+ group.tours.push(item);
+ }
}
});
@@ -162,7 +164,7 @@
newGroup.groupOrder = item.groupOrder;
}
- if(item.hidden === false){
+ if (item.hidden === false) {
newGroup.tours.push(item);
groupedTours.push(newGroup);
}
@@ -242,14 +244,14 @@
throw "Tour " + tour.alias + " is missing the required sections";
}
}
-
+
/**
* Validates a tour before it gets registered in the service
* @param {any} tour
*/
function validateTourRegistration(tour) {
// check for existing tours with the same alias
- angular.forEach(tours, function (existingTour) {
+ Utilities.forEach(tours, existingTour => {
if (existingTour.alias === tour.alias) {
throw "A tour with the alias " + tour.alias + " is already registered";
}
@@ -265,16 +267,17 @@
var deferred = $q.defer();
currentUserResource.getTours().then(function (storedTours) {
- angular.forEach(storedTours, function (storedTour) {
+ Utilities.forEach(storedTours, storedTour => {
+
if (storedTour.completed === true) {
- angular.forEach(tours, function (tour) {
+ Utilities.forEach(tours, tour => {
if (storedTour.alias === tour.alias) {
tour.completed = true;
}
});
}
if (storedTour.disabled === true) {
- angular.forEach(tours, function (tour) {
+ Utilities.forEach(tours, tour => {
if (storedTour.alias === tour.alias) {
tour.disabled = true;
}
@@ -296,7 +299,7 @@
getCurrentTour: getCurrentTour,
getGroupedTours: getGroupedTours,
getTourByAlias: getTourByAlias,
- getToursForDoctype : getToursForDoctype
+ getToursForDoctype: getToursForDoctype
};
return service;
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js
index 3c9846fc43..0d6216f7cc 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js
@@ -47,7 +47,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
/** Internal method to track expanded paths on a tree */
_trackExpandedPaths: function (node, expandedPaths) {
- if (!node.children || !angular.isArray(node.children) || node.children.length == 0) {
+ if (!node.children || !Utilities.isArray(node.children) || node.children.length == 0) {
return;
}
@@ -174,7 +174,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
//we determine this based on the server variables
if (Umbraco.Sys.ServerVariables.umbracoPlugins &&
Umbraco.Sys.ServerVariables.umbracoPlugins.trees &&
- angular.isArray(Umbraco.Sys.ServerVariables.umbracoPlugins.trees)) {
+ Utilities.isArray(Umbraco.Sys.ServerVariables.umbracoPlugins.trees)) {
var found = _.find(Umbraco.Sys.ServerVariables.umbracoPlugins.trees, function (item) {
return invariantEquals(item.alias, treeAlias);
@@ -473,7 +473,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
for (var i = 0; i < treeNode.children.length; i++) {
var child = treeNode.children[i];
- if (child.children && angular.isArray(child.children) && child.children.length > 0) {
+ if (child.children && Utilities.isArray(child.children) && child.children.length > 0) {
//recurse
found = this.getDescendantNode(child, id);
if (found) {
@@ -773,7 +773,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
if (!args.path) {
throw "No path defined on args object for syncTree";
}
- if (!angular.isArray(args.path)) {
+ if (!Utilities.isArray(args.path)) {
throw "Path must be an array";
}
if (args.path.length < 1) {
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js
index d9aef1ddba..109fff0919 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js
@@ -64,7 +64,7 @@
var saveModel = _.pick(displayModel,
'compositeContentTypes', 'isContainer', 'allowAsRoot', 'allowedTemplates', 'allowedContentTypes',
'alias', 'description', 'thumbnail', 'name', 'id', 'icon', 'trashed',
- 'key', 'parentId', 'alias', 'path', 'allowCultureVariant', 'isElement');
+ 'key', 'parentId', 'alias', 'path', 'allowCultureVariant', 'allowSegmentVariant', 'isElement');
// TODO: Map these
saveModel.allowedTemplates = _.map(displayModel.allowedTemplates, function (t) { return t.alias; });
@@ -83,7 +83,7 @@
});
var saveProperties = _.map(realProperties, function (p) {
- var saveProperty = _.pick(p, 'id', 'alias', 'description', 'validation', 'label', 'sortOrder', 'dataTypeId', 'groupId', 'memberCanEdit', 'showOnMemberProfile', 'isSensitiveData', 'allowCultureVariant');
+ var saveProperty = _.pick(p, 'id', 'alias', 'description', 'validation', 'label', 'sortOrder', 'dataTypeId', 'groupId', 'memberCanEdit', 'showOnMemberProfile', 'isSensitiveData', 'allowCultureVariant', 'allowSegmentVariant');
return saveProperty;
});
@@ -158,7 +158,7 @@
var currGroups = saveModel.userGroups;
var formattedGroups = [];
for (var i = 0; i < currGroups.length; i++) {
- if (!angular.isString(currGroups[i])) {
+ if (!Utilities.isString(currGroups[i])) {
formattedGroups.push(currGroups[i].alias);
}
else {
@@ -229,7 +229,7 @@
var currSections = saveModel.sections;
var formattedSections = [];
for (var i = 0; i < currSections.length; i++) {
- if (!angular.isString(currSections[i])) {
+ if (!Utilities.isString(currSections[i])) {
formattedSections.push(currSections[i].alias);
}
else {
@@ -242,7 +242,7 @@
var currUsers = saveModel.users;
var formattedUsers = [];
for (var j = 0; j < currUsers.length; j++) {
- if (!angular.isNumber(currUsers[j])) {
+ if (!Utilities.isNumber(currUsers[j])) {
formattedUsers.push(currUsers[j].id);
}
else {
@@ -367,6 +367,7 @@
name: v.name || "", //if its null/empty,we must pass up an empty string else we get json converter errors
properties: getContentProperties(v.tabs),
culture: v.language ? v.language.culture : null,
+ segment: v.segment,
publish: v.publish,
save: v.save,
releaseDate: v.releaseDate,
@@ -393,38 +394,59 @@
*/
formatContentGetData: function(displayModel) {
- //We need to check for invariant properties among the variant variants.
- //When we detect this, we want to make sure that the property object instance is the
- //same reference object between all variants instead of a copy (which it will be when
- //return from the JSON structure).
+ // We need to check for invariant properties among the variant variants,
+ // as the value of an invariant property is shared between different variants.
+ // A property can be culture invariant, segment invariant, or both.
+ // When we detect this, we want to make sure that the property object instance is the
+ // same reference object between all variants instead of a copy (which it will be when
+ // return from the JSON structure).
if (displayModel.variants && displayModel.variants.length > 1) {
+ // Collect all invariant properties from the variants that are either the
+ // default language variant or the default segment variant.
+ var defaultVariants = _.filter(displayModel.variants, function (variant) {
+ var isDefaultLanguage = variant.language && variant.language.isDefault;
+ var isDefaultSegment = variant.segment == null;
- var invariantProperties = [];
-
- //collect all invariant properties on the first first variant
- var firstVariant = displayModel.variants[0];
- _.each(firstVariant.tabs, function(tab, tabIndex) {
- _.each(tab.properties, function (property, propIndex) {
- //in theory if there's more than 1 variant, that means they would all have a language
- //but we'll do our safety checks anyways here
- if (firstVariant.language && !property.culture) {
- invariantProperties.push({
- tabIndex: tabIndex,
- propIndex: propIndex,
- property: property
- });
- }
- });
+ return isDefaultLanguage || isDefaultSegment;
});
+ if (defaultVariants.length > 0) {
+ _.each(defaultVariants, function (defaultVariant) {
+ var invariantProps = [];
- //now assign this same invariant property instance to the same index of the other variants property array
- for (var j = 1; j < displayModel.variants.length; j++) {
- var variant = displayModel.variants[j];
+ _.each(defaultVariant.tabs, function (tab, tabIndex) {
+ _.each(tab.properties, function (property, propIndex) {
+ // culture == null -> property is culture invariant
+ // segment == null -> property is *possibly* segment invariant
+ if (!property.culture || !property.segment) {
+ invariantProps.push({
+ tabIndex: tabIndex,
+ propIndex: propIndex,
+ property: property
+ });
+ }
+ });
+ });
- _.each(invariantProperties, function (invProp) {
- variant.tabs[invProp.tabIndex].properties[invProp.propIndex] = invProp.property;
+ var otherVariants = _.filter(displayModel.variants, function (variant) {
+ return variant !== defaultVariant;
+ });
+
+ // now assign this same invariant property instance to the same index of the other variants property array
+ _.each(otherVariants, function (variant) {
+ _.each(invariantProps, function (invProp) {
+ var tab = variant.tabs[invProp.tabIndex];
+ var prop = tab.properties[invProp.propIndex];
+
+ var inheritsCulture = prop.culture === invProp.property.culture && prop.segment == null && invProp.property.segment == null;
+ var inheritsSegment = prop.segment === invProp.property.segment && !prop.culture;
+
+ if (inheritsCulture || inheritsSegment) {
+ tab.properties[invProp.propIndex] = invProp.property;
+ }
+ });
+ });
});
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js
index 0d766dc7d8..4cbc5e567a 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js
@@ -44,7 +44,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
*/
dictionaryToQueryString: function (queryStrings) {
- if (angular.isArray(queryStrings)) {
+ if (Utilities.isArray(queryStrings)) {
return _.map(queryStrings, function (item) {
var key = null;
var val = null;
@@ -59,7 +59,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
return encodeURIComponent(key) + "=" + encodeURIComponent(val);
}).join("&");
}
- else if (angular.isObject(queryStrings)) {
+ else if (Utilities.isObject(queryStrings)) {
//this allows for a normal object to be passed in (ie. a dictionary)
return decodeURIComponent($.param(queryStrings));
@@ -91,7 +91,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
}
return Umbraco.Sys.ServerVariables["umbracoUrls"][apiName] + actionName +
- (!queryStrings ? "" : "?" + (angular.isString(queryStrings) ? queryStrings : this.dictionaryToQueryString(queryStrings)));
+ (!queryStrings ? "" : "?" + (Utilities.isString(queryStrings) ? queryStrings : this.dictionaryToQueryString(queryStrings)));
},
@@ -129,7 +129,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
var err = {
//NOTE: the default error message here should never be used based on the above docs!
- errorMsg: (angular.isString(opts) ? opts : 'An error occurred!'),
+ errorMsg: (Utilities.isString(opts) ? opts : 'An error occurred!'),
data: data,
status: status
};
@@ -252,12 +252,13 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
for (var f in args.files) {
//each item has a property alias and the file object, we'll ensure that the alias is suffixed to the key
// so we know which property it belongs to on the server side
- var fileKey = "file_" + args.files[f].alias + "_" + (args.files[f].culture ? args.files[f].culture : "");
+ var file = args.files[f];
+ var fileKey = "file_" + file.alias + "_" + (file.culture ? file.culture : "") + "_" + (file.segment ? file.segment : "");
- if (angular.isArray(args.files[f].metaData) && args.files[f].metaData.length > 0) {
- fileKey += ("_" + args.files[f].metaData.join("_"));
+ if (Utilities.isArray(file.metaData) && file.metaData.length > 0) {
+ fileKey += ("_" + file.metaData.join("_"));
}
- formData.append(fileKey, args.files[f].file);
+ formData.append(fileKey, file.file);
}
}).then(function (response) {
//success callback
@@ -322,7 +323,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
//validate input, jsonData can be an array of key/value pairs or just one key/value pair.
if (!jsonData) { throw "jsonData cannot be null"; }
- if (angular.isArray(jsonData)) {
+ if (Utilities.isArray(jsonData)) {
_.each(jsonData, function (item) {
if (!item.key || !item.value) { throw "jsonData array item must have both a key and a value property"; }
});
@@ -340,13 +341,13 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
transformRequest: function(data) {
var formData = new FormData();
//add the json data
- if (angular.isArray(data)) {
+ if (Utilities.isArray(data)) {
_.each(data, function(item) {
- formData.append(item.key, !angular.isString(item.value) ? angular.toJson(item.value) : item.value);
+ formData.append(item.key, !Utilities.isString(item.value) ? Utilities.toJson(item.value) : item.value);
});
}
else {
- formData.append(data.key, !angular.isString(data.value) ? angular.toJson(data.value) : data.value);
+ formData.append(data.key, !Utilities.isString(data.value) ? Utilities.toJson(data.value) : data.value);
}
//call the callback
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js
index afd7b606e7..de6fbaf782 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js
@@ -128,7 +128,7 @@ angular.module('umbraco.services')
function setUserTimeoutInternal(newTimeout) {
var asNumber = parseFloat(newTimeout);
- if (!isNaN(asNumber) && currentUser && angular.isNumber(asNumber)) {
+ if (!isNaN(asNumber) && currentUser && Utilities.isNumber(asNumber)) {
currentUser.remainingAuthSeconds = newTimeout;
lastServerTimeoutSet = new Date();
}
@@ -185,7 +185,19 @@ angular.module('umbraco.services')
authenticate: function (login, password) {
return authResource.performLogin(login, password)
- .then(this.setAuthenticationSuccessful);
+ .then(function(data) {
+
+ // Check if user has a start node set.
+ if(data.startContentIds.length === 0 && data.startMediaIds.length === 0){
+ var errorMsg = "User has no start-nodes";
+ var result = { errorMsg: errorMsg, user: data, authenticated: false, lastUserId: lastUserId, loginType: "credentials" };
+ eventsService.emit("app.notAuthenticated", result);
+ throw result;
+ }
+
+ return data;
+
+ }).then(this.setAuthenticationSuccessful);
},
setAuthenticationSuccessful: function (data) {
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js
index a7ff9def21..82353df744 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js
@@ -206,11 +206,11 @@ function umbSessionStorage($window) {
return {
get: function (key) {
- return angular.fromJson(storage["umb_" + key]);
+ return Utilities.fromJson(storage["umb_" + key]);
},
set: function (key, value) {
- storage["umb_" + key] = angular.toJson(value);
+ storage["umb_" + key] = Utilities.toJson(value);
}
};
diff --git a/src/Umbraco.Web.UI.Client/src/init.js b/src/Umbraco.Web.UI.Client/src/init.js
index d5c5166d21..ce824f63c0 100644
--- a/src/Umbraco.Web.UI.Client/src/init.js
+++ b/src/Umbraco.Web.UI.Client/src/init.js
@@ -34,7 +34,7 @@ app.run(['$rootScope', '$route', '$location', 'urlHelper', 'navigationService',
else {
const introTourShown = localStorageService.get("introTourShown");
- if(!introTourShown){
+ if (!introTourShown) {
// Go & show email marketing tour (ONLY when intro tour is completed or been dismissed)
tourService.getTourByAlias("umbEmailMarketing").then(function (emailMarketingTour) {
// Only show the email marketing tour one time - dismissing it or saying no will make sure it never appears again
@@ -45,7 +45,7 @@ app.run(['$rootScope', '$route', '$location', 'urlHelper', 'navigationService',
// Only show the email tour once per logged in session
// The localstorage key is removed on logout or user session timeout
const emailMarketingTourShown = localStorageService.get("emailMarketingTourShown");
- if(!emailMarketingTourShown){
+ if (!emailMarketingTourShown) {
tourService.startTour(emailMarketingTour);
localStorageService.set("emailMarketingTourShown", true);
}
@@ -89,7 +89,7 @@ app.run(['$rootScope', '$route', '$location', 'urlHelper', 'navigationService',
currentRouteParams = toRetain;
}
else {
- currentRouteParams = angular.copy(current.params);
+ currentRouteParams = Utilities.copy(current.params);
}
@@ -183,7 +183,7 @@ app.run(['$rootScope', '$route', '$location', 'urlHelper', 'navigationService',
currentRouteParams = toRetain;
}
else {
- currentRouteParams = angular.copy(next.params);
+ currentRouteParams = Utilities.copy(next.params);
}
//always clear the 'sr' query string (soft redirect) if it exists
@@ -191,7 +191,7 @@ app.run(['$rootScope', '$route', '$location', 'urlHelper', 'navigationService',
currentRouteParams.sr = null;
$route.updateParams(currentRouteParams);
}
-
+
}
}
});
diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less
index 6c021203a5..0a2ac07ab1 100644
--- a/src/Umbraco.Web.UI.Client/src/less/belle.less
+++ b/src/Umbraco.Web.UI.Client/src/less/belle.less
@@ -107,6 +107,7 @@
@import "components/overlays.less";
@import "components/card.less";
@import "components/editor/umb-editor.less";
+@import "components/editor/umb-variant-switcher.less";
@import "components/umb-sub-views.less";
@import "components/umb-editor-navigation.less";
@import "components/umb-editor-navigation-item.less";
@@ -137,6 +138,7 @@
@import "components/tooltip/umb-tooltip-list.less";
@import "components/overlays/umb-overlay-backdrop.less";
@import "components/overlays/umb-itempicker.less";
+@import "components/overlays/umb-variant-selector-overlay";
@import "components/umb-grid.less";
@import "components/umb-empty-state.less";
@import "components/umb-property-editor.less";
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/application/umb-dashboard.less b/src/Umbraco.Web.UI.Client/src/less/components/application/umb-dashboard.less
index 52ff2c2b01..03153973ff 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/application/umb-dashboard.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/application/umb-dashboard.less
@@ -31,6 +31,6 @@
border: none;
}
-.umb-dashboard__header .umb-tabs-nav .umb-tab > a {
+.umb-dashboard__header .umb-tabs-nav .umb-tab > .umb-tab-button {
padding-bottom: 25px;
}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/card.less b/src/Umbraco.Web.UI.Client/src/less/components/card.less
index 112182fa88..017468fa0c 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/card.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/card.less
@@ -2,20 +2,28 @@
Library of card related compoents, like the right-hand icon list on the grid "cards"
*/
-.umb-card{
+.umb-card {
position: relative;
padding: 5px 10px 5px 10px;
background: @white;
width: 100%;
- .title{padding: 12px; color: @gray-3; border-bottom: 1px solid @gray-8; font-weight: 400; font-size: 16px; text-transform: none; margin: 0 -10px 10px -10px;}
+ .title {
+ padding: 12px;
+ color: @gray-3;
+ border-bottom: 1px solid @gray-8;
+ font-weight: 400;
+ font-size: 16px;
+ text-transform: none;
+ margin: 0 -10px 10px -10px;
+ }
}
-.umb-card-thumb{
+.umb-card-thumb {
text-align: center;
- i{
+ i {
text-align: center;
font-size: 20px;
line-height: 40px;
@@ -25,18 +33,28 @@
}
}
-.umb-card-content{
- .item-title{color: @blackLight; font-weight: 400; border: none; font-size: 16px; text-transform: none; margin-bottom: 3px;}
- p{color: @gray-3; margin-bottom: 1px;}
+.umb-card-content {
+ .item-title {
+ color: @blackLight;
+ font-weight: 400;
+ border: none;
+ font-size: 16px;
+ text-transform: none;
+ margin-bottom: 3px;
+ }
+ p {
+ color: @gray-3;
+ margin-bottom: 1px;
+ }
}
-.umb-card-actions{
+.umb-card-actions {
padding-top: 10px;
border-top: @gray-10 1px solid;
clear: both;
}
-.umb-card-icons{
+.umb-card-icons {
text-align: center;
vertical-align: middle;
display: block;
@@ -45,7 +63,7 @@
padding: 0;
}
-.umb-card-icons.vertical{
+.umb-card-icons.vertical {
position: absolute;
top: 7px;
right: 7px;
@@ -53,19 +71,19 @@
width: 1px;
}
-.umb-card-icons li{
+.umb-card-icons li {
display: inline-block;
margin: 0 2px 0 2px;
}
-.umb-card-icons.vertical li{
+.umb-card-icons.vertical li {
float: right;
display: block;
margin-bottom: 3px;
}
//card iocn list
-.umb-card-list{
+.umb-card-list {
display: block;
padding: 0;
margin: 0;
@@ -81,7 +99,7 @@
//Card icon grid for picking items off a card
-.umb-card-grid{
+.umb-card-grid {
padding: 0;
margin: 0 auto;
list-style: none;
@@ -101,14 +119,24 @@
width: 100px;
}
+.umb-card-grid.-six-in-row li {
+ flex: 0 0 25%;
+ max-width: 117px;
+}
+
.umb-card-grid.-four-in-row li {
flex: 0 0 25%;
max-width: 25%;
}
.umb-card-grid.-three-in-row li {
- flex: 0 0 33.33%;
- max-width:33.33%;
+ flex: 0 0 33.333%;
+ max-width:33.333%;
+
+ i {
+ font-size: 36px;
+ line-height: 28px;
+ }
}
.umb-card-grid .umb-card-grid-item {
@@ -117,7 +145,7 @@
width: 100%;
//height: 100%;
padding-top: 100%;
- border-radius: 3px;
+ border-radius: @baseBorderRadius * 2;
transition: background-color 120ms;
> span {
@@ -153,6 +181,41 @@
}
}
+.umb-card-grid .umb-card-grid-item-slot {
+ position: relative;
+ display: block;
+ width: 100%;
+ padding-top: 100%;
+ border-radius: @baseBorderRadius * 2;
+
+ box-sizing: border-box;
+ transition: background-color 120ms;
+
+ &:hover, &:focus {
+ background-color: @ui-option-hover;
+ > span {
+ color:@ui-action-discreet-type-hover;
+ border-color:@ui-action-discreet-border-hover;
+ }
+ }
+
+ > span {
+ position: absolute;
+ top: 10px;
+ bottom: 10px;
+ left: 10px;
+ right: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ background-color: transparent;
+ border:1.5px dashed @ui-action-discreet-border;
+ border-radius: @baseBorderRadius * 2;
+ }
+}
+
+
.umb-card-grid a {
color: @ui-option-type;
text-decoration: none;
@@ -161,6 +224,7 @@
.umb-card-grid i {
font-size: 30px;
line-height: 20px;
+ margin-top: 6px;
margin-bottom: 10px;
display: block;
}
@@ -176,7 +240,7 @@
//Round icon-like button - this should be somewhere else
-.umb-btn-round{
+.umb-btn-round {
padding: 4px 6px 4px 6px;
display: inline-block;
cursor: pointer;
@@ -186,7 +250,8 @@
margin: 2px;
}
-.umb-btn-round:hover, .umb-btn-round:hover *{
+.umb-btn-round:hover,
+.umb-btn-round:hover * {
background: @blueDark !important;
color: @white !important;
border-color: @blueDark !important;
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor.less b/src/Umbraco.Web.UI.Client/src/less/components/editor.less
index bc84b0d35e..ac55c6ffb1 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/editor.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/editor.less
@@ -162,161 +162,6 @@ a.umb-editor-header__close-split-view:hover {
}
}
-/* variant switcher */
-.umb-variant-switcher__toggle {
- position: relative;
- display: flex;
- align-items: center;
- padding: 0 10px;
- margin: 1px 1px;
- right: 0;
- height: 30px;
- text-decoration: none !important;
- font-size: 13px;
- color: @ui-action-discreet-type;
- background: transparent;
- border: none;
-
- max-width: 50%;
- white-space: nowrap;
-
- user-select: none;
-
- span {
- text-overflow: ellipsis;
- overflow: hidden;
- }
-}
-
-button.umb-variant-switcher__toggle {
- transition: color 0.2s ease-in-out;
- &:hover {
- //background-color: @gray-10;
- color: @ui-action-discreet-type-hover;
- .umb-variant-switcher__expand {
- color: @ui-action-discreet-type-hover;
- }
- }
-
- &.--error {
- &::before {
- content: '!';
- position: absolute;
- top: -8px;
- right: -10px;
- display: inline-flex;
- align-items: center;
- justify-content: center;
- width: 20px;
- height: 20px;
- border-radius: 10px;
- text-align: center;
- font-weight: bold;
- background-color: @errorBackground;
- color: @errorText;
- }
- }
-}
-
-.umb-variant-switcher__expand {
- color: @ui-action-discreet-type;
- margin-top: 3px;
- margin-left: 5px;
- margin-right: -5px;
- transition: color 0.2s ease-in-out;
-}
-
-.umb-variant-switcher__item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- border-bottom: 1px solid @gray-9;
- position: relative;
-}
-
-.umb-variant-switcher__item:last-child {
- border-bottom: none;
-}
-
-.umb-variant-switcher__item.--current {
- color: @ui-light-active-type;
-}
-.umb-variant-switcher__item.--current .umb-variant-switcher__name-wrapper {
- border-left: 4px solid @ui-active;
-}
-
-.umb-variant-switcher__item:hover {
- outline: none;
-}
-
-.umb-variant-switcher__item.--not-allowed:not(.--current) .umb-variant-switcher__name-wrapper:hover {
- //background-color: @white !important;
- cursor: default;
-}
-
-.umb-variant-switcher__item:hover .umb-variant-switcher__split-view {
- display: block;
- cursor: pointer;
-}
-
-.umb-variant-switcher__item.--error {
- .umb-variant-switcher__name {
- color: @red;
- &::after {
- content: '!';
- position: relative;
- display: inline-flex;
- align-items: center;
- justify-content: center;
- margin-left: 5px;
- top: -3px;
- width: 14px;
- height: 14px;
- border-radius: 7px;
- font-size: 8px;
- text-align: center;
- font-weight: bold;
- background-color: @errorBackground;
- color: @errorText;
- }
- }
-}
-
-.umb-variant-switcher__name-wrapper {
- font-size: 14px;
- flex: 1;
- cursor: pointer;
- padding-top: 6px !important;
- padding-bottom: 6px !important;
- background-color: transparent;
- border: none;
- border-left: 2px solid transparent;
-}
-
-.umb-variant-switcher__name {
- display: block;
-}
-
-.umb-variant-switcher__state {
- font-size: 13px;
- color: @gray-4;
-}
-
-.umb-variant-switcher__split-view {
- font-size: 13px;
- display: none;
- padding: 16px 20px;
- position: absolute;
- right: 0;
- top: 0;
- bottom: 0;
- background-color: @white;
-
- &:hover {
- background-color: @ui-option-hover;
- color: @ui-option-type-hover;
- }
-}
// container
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor/subheader/umb-editor-sub-header.less b/src/Umbraco.Web.UI.Client/src/less/components/editor/subheader/umb-editor-sub-header.less
index 4ebfa94b6f..3c4a037b0b 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/editor/subheader/umb-editor-sub-header.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/editor/subheader/umb-editor-sub-header.less
@@ -5,7 +5,7 @@
border-right: 5px solid @brownGrayLight;
display: flex;
justify-content: space-between;
- margin: -10px -5px 10px;
+ margin: -10px -1px 10px;
position: relative;
top: 0;
box-sizing: border-box;
@@ -34,6 +34,7 @@
transition: box-shadow 240ms;
position:sticky;
z-index: 30;
+ width: calc(100% + 2px);
&.umb-sticky-bar--active {
box-shadow: 0 6px 3px -3px rgba(0,0,0,.16);
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less
index d2a3bdedb1..e81df77772 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-editor.less
@@ -1,6 +1,7 @@
.umb-editors {
.absolute();
overflow: hidden;
+ z-index: 7500;
.umb-editor {
box-shadow: 0px 0 30px 0 rgba(0,0,0,.3);
@@ -104,4 +105,4 @@
i {
margin-right:5px;
}
-}
\ No newline at end of file
+}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less
new file mode 100644
index 0000000000..8dbc070856
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less
@@ -0,0 +1,332 @@
+/* variant switcher */
+.umb-variant-switcher__toggle {
+ position: relative;
+ display: flex;
+ align-items: center;
+ padding: 0 10px;
+ margin: 1px 1px;
+ right: 0;
+ height: 30px;
+ text-decoration: none !important;
+ font-size: 13px;
+ color: @ui-action-discreet-type;
+ background: transparent;
+ border: none;
+
+ max-width: 50%;
+ white-space: nowrap;
+
+ user-select: none;
+
+ span {
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+}
+
+button.umb-variant-switcher__toggle {
+ transition: color 0.2s ease-in-out;
+ &:hover {
+ //background-color: @gray-10;
+ color: @ui-action-discreet-type-hover;
+ .umb-variant-switcher__expand {
+ color: @ui-action-discreet-type-hover;
+ }
+ }
+
+ &.--error {
+ &::before {
+ content: '!';
+ position: absolute;
+ top: -8px;
+ right: -10px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 20px;
+ height: 20px;
+ border-radius: 10px;
+ text-align: center;
+ font-weight: bold;
+ background-color: @errorBackground;
+ color: @errorText;
+ }
+ }
+}
+
+.umb-variant-switcher__expand {
+ color: @ui-action-discreet-type;
+ margin-top: 3px;
+ margin-left: 5px;
+ margin-right: -5px;
+ transition: color 0.2s ease-in-out;
+}
+
+
+.umb-variant-switcher {
+ min-width: 100%;
+ max-height: 80vh;
+ overflow-y: auto;
+ margin-top: 5px;
+ user-select: none;
+}
+
+.umb-variant-switcher__item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: 1px solid @gray-9;
+ position: relative;
+ .umb-variant-switcher__name-wrapper:hover {
+ .umb-variant-switcher__name {
+ color: @blueMid;
+ }
+ .umb-variant-switcher__state {
+ color: @blueMid;
+ }
+ }
+}
+.umb-variant-switcher__item.--state-notCreated:not(.--active) {
+ .umb-variant-switcher__name-wrapper::before {
+ content: "+";
+ display: block;
+ float: left;
+ font-size: 15px;
+ font-weight: 900;
+ padding: 8px 16px 8px 6px;
+ color: @gray-5;
+ }
+ .umb-variant-switcher__item-expand-button + .umb-variant-switcher__name-wrapper::before {
+ padding: 8px 16px 8px 20px;
+ }
+ .umb-variant-switcher__name {
+ color: @gray-5;
+ }
+ .umb-variant-switcher__state {
+ color: @gray-6;
+ }
+ .umb-variant-switcher__name-wrapper::after {
+ content: "";
+ position: absolute;
+ z-index: 1;
+ border: 1px dashed @gray-9;
+ top: 7px;
+ bottom: 7px;
+ left: 7px;
+ right: 7px;
+ border-radius: 3px;
+ pointer-events: none;
+ }
+
+ .umb-variant-switcher__name-wrapper:hover {
+ &::before {
+ color: @blueMid;
+ }
+ .umb-variant-switcher__name {
+ color: @blueMid;
+ }
+ .umb-variant-switcher__state {
+ color: @blueMid;
+ }
+ }
+}
+/*
+.umb-variant-switcher__item.--state-draft {
+ .umb-variant-switcher__name {
+ color: @gray-5;
+ }
+ &:hover {
+ .umb-variant-switcher__name {
+ color: @blueMid;
+ }
+ }
+}
+*/
+
+.umb-variant-switcher.--has-sub-variants {
+ .umb-variant-switcher__item {
+
+ }
+}
+
+.umb-variant-switcher__item-expand-button {
+ text-decoration: none;
+ display: inline-block;
+ flex: 0;
+ align-self: stretch;
+
+ padding-left: 22px !important;
+ padding-right: 14px !important;
+
+ font-size: 12px;
+
+ * {
+ pointer-events: none;
+ }
+}
+
+.umb-variant-switcher__item:last-child {
+ border-bottom: none;
+}
+
+.umb-variant-switcher__item.--current {
+ //color: @ui-light-active-type;
+ //background-color: @pinkExtraLight;
+ .umb-variant-switcher__name {
+ //color: @ui-light-active-type;
+ font-weight: 700;
+ }
+ &::before {
+ content: '';
+ position: absolute;
+ border-radius: 0 4px 4px 0;
+ background-color: @ui-active-border;
+ width: 4px;
+ top:8px;
+ bottom: 8px;
+ left:0;
+ z-index:1;
+ pointer-events: none;
+ }
+}
+
+.umb-variant-switcher__item:hover {
+ outline: none;
+}
+
+.umb-variant-switcher__item.--active:not(.--current) .umb-variant-switcher__name-wrapper:hover {
+ //background-color: @white !important;
+ cursor: default;
+}
+
+.umb-variant-switcher__item:focus .umb-variant-switcher__split-view,
+.umb-variant-switcher__item:focus-within .umb-variant-switcher__split-view,
+.umb-variant-switcher__item:hover .umb-variant-switcher__split-view,
+.umb-variant-switcher__split-view:focus {
+ display: block;
+ cursor: pointer;
+}
+
+.umb-variant-switcher__item.--error {
+ .umb-variant-switcher__name {
+ color: @red;
+ &::after {
+ content: '!';
+ position: relative;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ margin-left: 5px;
+ top: -3px;
+ width: 14px;
+ height: 14px;
+ border-radius: 7px;
+ font-size: 8px;
+ text-align: center;
+ font-weight: bold;
+ background-color: @errorBackground;
+ color: @errorText;
+ }
+ }
+}
+
+.umb-variant-switcher__name-wrapper {
+ font-size: 14px;
+ text-align: left;
+ flex: 1;
+ cursor: pointer;
+ background-color: transparent;
+ border: none;
+}
+.dropdown-menu>li {
+ > .umb-variant-switcher__name-wrapper {
+ padding-top: 10px;
+ padding-bottom: 10px;
+ }
+
+ > .umb-variant-switcher__item-expand-button + .umb-variant-switcher__name-wrapper {
+ padding-left: 5px;
+ }
+}
+
+
+.umb-variant-switcher__name {
+ display: block;
+ font-weight: 600;
+ margin-bottom: -2px;
+}
+
+.umb-variant-switcher__state {
+ font-size: 12px;
+ color: @gray-4;
+}
+
+.umb-variant-switcher__split-view {
+ font-size: 12px;
+ display: none;
+ padding: 20px 20px;
+ position: absolute;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ background-color: @white;
+
+ &:hover {
+ background-color: @ui-option-hover;
+ color: @ui-option-type-hover;
+ }
+}
+
+
+.umb-variant-switcher__sub-variants {
+
+ position: relative;
+ border-bottom: 1px solid @gray-9;
+ background-color: @gray-13;
+ /*
+ &::before {
+ content: "";
+ position: absolute;
+ z-index: 1;
+ top: 0px;
+ left: 20px;
+ width: 4px;
+ bottom: 14px;
+ border-bottom-left-radius: 2px;
+ border-bottom-right-radius: 2px;
+ background-color: @gray-8;
+ }
+ */
+ .umb-variant-switcher__item {
+ border-bottom-color: @gray-10;
+ }
+
+ .umb-variant-switcher__item.--state-notCreated:not(.--active) {
+ .umb-variant-switcher__name-wrapper::after {
+ left: 55px;// overwrite left to achieve same indentation on the dashed border as language.
+ }
+ }
+
+ .umb-variant-switcher__name-wrapper {
+
+ margin-left: 48px;
+ padding-left: 20px;
+
+ padding-top: 10px;
+ padding-bottom: 10px;
+
+ &:hover {
+ color: @ui-option-type-hover;
+ background-color: @ui-option-hover;
+ }
+
+ .umb-variant-switcher__name {
+ //margin-right: 20px;
+ }
+ .umb-variant-switcher__state {
+ //flex: 0 0 200px;
+ }
+
+
+ }
+}
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 bbd866a5fd..26a4abc146 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/overlays.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/overlays.less
@@ -2,7 +2,7 @@
position: fixed;
overflow: hidden;
background: @white;
- z-index: @zindexUmbOverlay;
+ z-index: 7501;
animation: fadeIn 0.2s;
box-shadow: 0 10px 50px rgba(0,0,0,0.1), 0 6px 20px rgba(0,0,0,0.16);
text-align: left;
@@ -24,16 +24,19 @@
margin-top: 0;
flex-grow: 0;
flex-shrink: 0;
- padding: 20px 20px 0;
+ padding: 30px 30px 0;
}
.umb-overlay__section-header {
width: 100%;
margin-top:30px;
- margin-bottom: 10px;
+ margin-bottom: 20px;
h5 {
display: inline;
+ font-size: 16px;
+ line-height: 16px;
+ font-weight: bold;
}
button {
@@ -66,7 +69,7 @@
flex-shrink: 1;
flex-basis: auto;
position: relative;
- padding: 30px;
+ padding: 20px 30px;
background: @white;
max-height: calc(100vh - 170px);
overflow-y: auto;
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/overlays/umb-itempicker.less b/src/Umbraco.Web.UI.Client/src/less/components/overlays/umb-itempicker.less
index 3727c92251..010ff4636d 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/overlays/umb-itempicker.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/overlays/umb-itempicker.less
@@ -1,6 +1,3 @@
.umb-itempicker .form-search {
margin-top:10px;
}
-.umb-card-grid {
- margin-top: 10px;
-}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/overlays/umb-variant-selector-overlay.less b/src/Umbraco.Web.UI.Client/src/less/components/overlays/umb-variant-selector-overlay.less
new file mode 100644
index 0000000000..b50a622f98
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/less/components/overlays/umb-variant-selector-overlay.less
@@ -0,0 +1,26 @@
+.umb-variant-selector-overlay {
+
+
+ .umb-variant-selector-entry {
+ .umb-form-check {
+ .umb-form-check__symbol {
+ margin-top: 2px;
+ }
+ }
+ }
+ .umb-variant-selector-entry__title {
+ font-weight: 600;
+ font-size: 14px;
+ .__secondarytitle {
+ font-weight: normal;
+ color: @gray-5;
+ }
+ }
+ .umb-variant-selector-entry__description {
+ display: block;
+ font-size: 12px;
+ color: @gray-4;
+ }
+
+
+}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less
index 2cca776614..f3c41dbc33 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less
@@ -178,11 +178,11 @@
}
// Validation
-.umb-sub-views-nav-item__action.-has-error,
+.show-validation .umb-sub-views-nav-item__action.-has-error,
.show-validation .umb-sub-views-nav-item > a.-has-error {
color: @red;
- &::after {
+ &::before {
background-color: @red;
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less
index f9d8772d45..ac7a2c63ce 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less
@@ -23,6 +23,7 @@
}
.umb-group-builder__group.-placeholder {
+ width:100%;
min-height: 86px;
display: flex;
justify-content: center;
@@ -136,9 +137,10 @@ input.umb-group-builder__group-title-input:disabled:hover {
}
.umb-group-builder__group-add-property {
- min-height: 46px;
- margin-right: 45px;
+
+ width: calc(100% - 315px);
margin-left: 270px;
+ min-height: 46px;
border-radius: 3px;
display: flex;
@@ -344,8 +346,9 @@ input.umb-group-builder__group-title-input:disabled:hover {
.umb-group-builder__property-actions {
flex: 0 0 44px;
- text-align: right;
- margin-top: 7px;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
}
.umb-group-builder__property-action {
@@ -473,7 +476,7 @@ input.umb-group-builder__group-sort-value {
font-weight: bold;
resize: none;
line-height: 1.5em;
- padding-left: 0;
+ padding: 0;
border: none;
&:focus {
@@ -498,45 +501,82 @@ input.umb-group-builder__group-sort-value {
text-decoration: none;
color: @ui-action-type-hover;
border-color: @ui-action-border-hover;
+ background-color: @ui-action-discreet-hover;
}
}
- .editor {
+ .editor-wrapper {
margin-bottom: 10px;
+ }
- .editor-icon-wrapper {
- border: 1px solid @gray-8;
- width: 60px;
- height: 60px;
- text-align: center;
- line-height: 60px;
- border-radius: 5px;
- float: left;
- margin-right: 20px;
+ .editor {
+ display: flex;
+ align-items: center;
+ align-content: stretch;
- .icon {
- font-size: 26px;
- }
+ min-height: 80px;
+
+ border: 1px solid @gray-9;
+ color: @ui-action-discreet-type;
+ border-radius: @baseBorderRadius;
+
+ }
+
+ .editor-info {
+ flex: 1 0 auto;
+ text-align: left;
+ display: flex;
+ align-items: center;
+ max-width: calc(100% - 48px);
+ min-height: 80px;
+ color: @ui-action-discreet-type;
+
+ &:hover {
+ color: @ui-action-discreet-type-hover;
+ background-color: @ui-action-discreet-hover;
+ }
+ }
+
+ .editor-icon-wrapper {
+ width: 60px;
+ height: 60px;
+ text-align: center;
+ line-height: 60px;
+ flex: 0 0 60px;
+ padding-left: 10px;
+
+ .icon {
+ font-size: 32px;
+ }
+ }
+
+ .editor-details {
+ flex: 1 1 auto;
+ margin-top: 10px;
+ margin-bottom: 10px;
+
+ .editor-name {
+ display: block;
+ font-weight: bold;
}
- .editor-details {
- float: left;
- margin-top: 10px;
-
- .editor-name {
- display: block;
- font-weight: bold;
- }
-
- .editor-editor {
- display: block;
- font-size: 12px;
- }
+ .editor-editor {
+ display: block;
+ font-size: 12px;
}
+ }
- .editor-settings-icon {
- font-size: 18px;
- margin-top: 8px;
+ .editor-remove-icon {
+ flex: 0 0 48px;
+ width: 48px;
+ height: 48px;
+ font-size: 18px;
+
+ min-height: 80px;
+ color: @ui-action-discreet-type;
+ &:hover {
+ color: @ui-action-discreet-type-hover;
+ background-color: @ui-action-discreet-hover;
}
}
@@ -544,6 +584,11 @@ input.umb-group-builder__group-sort-value {
margin-bottom: 20px;
}
+ .editor-description {
+ margin-top: 20px;
+ padding: 0;
+ }
+
.editor-description,
.editor-validation-pattern {
min-width: 100%;
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less
index 94cfa6f62c..44955e8f8e 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less
@@ -1,15 +1,18 @@
.umb-list--condensed {
.umb-list-item {
- padding-top: 5px;
- padding-bottom: 5px;
+ padding-top: 7px;
+ padding-bottom: 7px;
}
}
.umb-list-item {
- border-bottom: 1px solid @gray-9;
+ border-bottom: 1px solid @gray-11;
padding-top: 15px;
padding-bottom: 15px;
display: flex;
+ &:last-of-type {
+ border-bottom: none;
+ }
}
a.umb-list-item:hover,
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-tabs.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-tabs.less
index ee784787fa..15b317aa45 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-tabs.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-tabs.less
@@ -13,25 +13,31 @@
top: 1px;
}
-.umb-tab > a {
-
+.umb-tab-button {
display: flex;
justify-content: center;
align-items: center;
position: relative;
-
+
cursor: pointer;
//border-bottom: 4px solid transparent;
color: @ui-light-type;
padding: 5px 20px 15px 20px;
transition: color 150ms ease-in-out;
+
&:focus {
color: @ui-light-type-hover;
+
+ body:not(.tabbing-active) &{
+ outline: none;
+ }
}
+
&:hover {
color: @ui-light-type-hover;
text-decoration: none;
}
+
&::after {
content: "";
height: 0px;
@@ -42,12 +48,21 @@
bottom: 0;
border-radius: 3px 3px 0 0;
opacity: 0;
- transition: all .2s linear;
+ transition: all 0.2s linear;
+ }
+
+ &--expand > i {
+ height: 5px;
+ width: 5px;
+ border-radius: 50%;
+ background: @black;
+ display: inline-block;
+ margin: 0 5px 0 0;
+ opacity: 0.6;
}
}
-
-.umb-tab--active > a {
+.umb-tab--active > .umb-tab-button {
color: @ui-light-active-type;
//border-bottom-color: @ui-active;
/*
@@ -64,19 +79,19 @@
}
}
-.show-validation .umb-tab--error > a,
-.show-validation .umb-tab--error > a:hover,
-.show-validation .umb-tab--error > a:focus {
- color: @white !important;
- background-color: @red !important;
- border-color: @errorBorder;
+.show-validation .umb-tab--error > .umb-tab-button,
+.show-validation .umb-tab--error > .umb-tab-button:hover,
+.show-validation .umb-tab--error > .umb-tab-button:focus {
+ color: @white !important;
+ background-color: @red !important;
+ border-color: @errorBorder;
}
-.show-validation .umb-tab--error a:before {
- content: "\e25d";
- font-family: 'icomoon';
- margin-right: 5px;
- vertical-align: top;
+.show-validation .umb-tab--error .umb-tab-button:before {
+ content: "\e25d";
+ font-family: "icomoon";
+ margin-right: 5px;
+ vertical-align: top;
}
// tabs tray
@@ -86,20 +101,10 @@
left: auto;
}
-.umb-tabs-tray > a {
+.umb-tabs-tray > .umb-tab-button {
cursor: pointer;
}
.umb-tabs-tray-item--active {
border-left: 2px solid @ui-active;
}
-
-.umb-tab--expand > a > i {
- height: 5px;
- width: 5px;
- border-radius: 50%;
- background: @black;
- display: inline-block;
- margin: 0 5px 0 0;
- opacity: .6;
-}
diff --git a/src/Umbraco.Web.UI.Client/src/less/forms/umb-validation-label.less b/src/Umbraco.Web.UI.Client/src/less/forms/umb-validation-label.less
index 9b4bac723b..e5b84fc6ca 100644
--- a/src/Umbraco.Web.UI.Client/src/less/forms/umb-validation-label.less
+++ b/src/Umbraco.Web.UI.Client/src/less/forms/umb-validation-label.less
@@ -1,13 +1,17 @@
.umb-validation-label {
position: absolute;
- top: 27px;
- min-width: 100px;
- max-width: 200px;
- padding: 1px 5px;
+ z-index: 1;
+ top: 28px;
+ min-width: 80px;
+ max-width: 260px;
+ padding: 2px 6px;
background: @red;
color: @white;
- font-size: 11px;
+ font-size: 12px;
line-height: 1.5em;
+ border-radius: @baseBorderRadius;
+ pointer-events: none;
+ user-select: none;
}
.umb-validation-label:after {
diff --git a/src/Umbraco.Web.UI.Client/src/less/pages/login.less b/src/Umbraco.Web.UI.Client/src/less/pages/login.less
index e36acdc273..818b1d84d1 100644
--- a/src/Umbraco.Web.UI.Client/src/less/pages/login.less
+++ b/src/Umbraco.Web.UI.Client/src/less/pages/login.less
@@ -123,6 +123,7 @@
position: relative;
text-align: right;
user-select: none;
+ margin-left: auto;
a {
opacity: .5;
@@ -134,8 +135,8 @@
.password-text {
background-repeat: no-repeat;
background-size: 18px;
- background-position: left center;
- padding-left: 26px;
+ background-position: 0px 1px;
+ padding-left: 24px;
&.show {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath fill='%23444' d='M16 6C9 6 3 10 0 16c3 6 9 10 16 10s13-4 16-10c-3-6-9-10-16-10zm8 5.3c1.8 1.2 3.4 2.8 4.6 4.7-1.2 2-2.8 3.5-4.7 4.7-3 1.5-6 2.3-8 2.3s-6-.8-8-2.3C6 19.5 4 18 3 16c1.5-2 3-3.5 5-4.7l.6-.2C8 12 8 13 8 14c0 4.5 3.5 8 8 8s8-3.5 8-8c0-1-.3-2-.6-2.6l.4.3zM16 13c0 1.7-1.3 3-3 3s-3-1.3-3-3 1.3-3 3-3 3 1.3 3 3z'/%3E%3C/svg%3E");
diff --git a/src/Umbraco.Web.UI.Client/src/less/properties.less b/src/Umbraco.Web.UI.Client/src/less/properties.less
index 8523fe9300..9e951feb1a 100644
--- a/src/Umbraco.Web.UI.Client/src/less/properties.less
+++ b/src/Umbraco.Web.UI.Client/src/less/properties.less
@@ -49,7 +49,7 @@
}
.date-wrapper-mini--checkbox{
- margin: 0 0 0 26px;
+ margin: 0 0 0 28px;
}
.date-wrapper-mini__date {
@@ -62,6 +62,10 @@
&:first-of-type {
margin-left: 0;
}
+ .flatpickr-input > button:first-of-type {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ }
}
.date-wrapper-mini__date .flatpickr-input > a {
diff --git a/src/Umbraco.Web.UI.Client/src/less/variables.less b/src/Umbraco.Web.UI.Client/src/less/variables.less
index c320a31807..26ec1d795a 100644
--- a/src/Umbraco.Web.UI.Client/src/less/variables.less
+++ b/src/Umbraco.Web.UI.Client/src/less/variables.less
@@ -83,6 +83,8 @@
@sand-5: #F3ECE8;// added 2019
@sand-6: #F6F1EF;// added 2019
@sand-7: #F9F7F5;// added 2019
+@sand-8: #fbfaf9;// added 2019
+@sand-9: #fdfcfc;// added 2019
// Additional Icon Colours
diff --git a/src/Umbraco.Web.UI.Client/src/main.controller.js b/src/Umbraco.Web.UI.Client/src/main.controller.js
index 55eb92ec04..d21331f106 100644
--- a/src/Umbraco.Web.UI.Client/src/main.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/main.controller.js
@@ -66,12 +66,14 @@ function MainController($scope, $location, appState, treeService, notificationsS
appState.setSearchState("show", false);
};
- $scope.showLoginScreen = function(isTimedOut) {
+ $scope.showLoginScreen = function (isTimedOut) {
+ $scope.login.pageTitle = $scope.$root.locationTitle;
$scope.login.isTimedOut = isTimedOut;
$scope.login.show = true;
};
- $scope.hideLoginScreen = function() {
+ $scope.hideLoginScreen = function () {
+ $scope.$root.locationTitle = $scope.login.pageTitle;
$scope.login.show = false;
};
@@ -82,6 +84,7 @@ function MainController($scope, $location, appState, treeService, notificationsS
$scope.authenticated = null;
$scope.user = null;
const isTimedOut = data && data.isTimedOut ? true : false;
+
$scope.showLoginScreen(isTimedOut);
// Remove the localstorage items for tours shown
diff --git a/src/Umbraco.Web.UI.Client/src/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/navigation.controller.js
index 281be2d331..a383c2d44a 100644
--- a/src/Umbraco.Web.UI.Client/src/navigation.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/navigation.controller.js
@@ -68,7 +68,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
args.event.stopPropagation();
args.event.preventDefault();
- if (n.metaData && n.metaData["jsClickCallback"] && angular.isString(n.metaData["jsClickCallback"]) && n.metaData["jsClickCallback"] !== "") {
+ if (n.metaData && n.metaData["jsClickCallback"] && Utilities.isString(n.metaData["jsClickCallback"]) && n.metaData["jsClickCallback"] !== "") {
//this is a legacy tree node!
var jsPrefix = "javascript:";
var js;
@@ -142,7 +142,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
var isInit = false;
var evts = [];
-
+
//Listen for global state changes
evts.push(eventsService.on("appState.globalState.changed", function (e, args) {
if (args.key === "showNavigation") {
@@ -200,7 +200,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
$scope.treeApi.load({ section: $scope.currentSection, customTreeParams: $scope.customTreeParams, cacheKey: $scope.treeCacheKey });
});
}
-
+
//show/hide search results
if (args.key === "showSearchResults") {
$scope.showSearchResults = args.value;
@@ -222,7 +222,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
} else {
$location.search("mculture", null);
}
-
+
var currentEditorState = editorState.getCurrent();
if (currentEditorState && currentEditorState.path) {
$scope.treeApi.syncTree({ path: currentEditorState.path, activate: true });
@@ -233,13 +233,13 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
//Emitted when a language is created or an existing one saved/edited
evts.push(eventsService.on("editors.languages.languageSaved", function (e, args) {
- if(args.isNew){
+ if (args.isNew) {
//A new language has been created - reload languages for tree
loadLanguages().then(function (languages) {
$scope.languages = languages;
});
}
- else if(args.language.isDefault){
+ else if (args.language.isDefault) {
//A language was saved and was set to be the new default (refresh the tree, so its at the top)
loadLanguages().then(function (languages) {
$scope.languages = languages;
@@ -282,7 +282,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
/**
* For multi language sites, this ensures that mculture is set to either the last selected language or the default one
- */
+ */
function ensureMainCulture() {
if ($location.search().mculture) {
return;
@@ -295,7 +295,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
$timeout(function () {
$scope.selectLanguage(language);
});
- }
+ }
/**
* Based on the current state of the application, this configures the scope variables that control the main tree and language drop down
@@ -432,7 +432,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
//the nav is ready, let the app know
eventsService.emit("app.navigationReady", { treeApi: $scope.treeApi });
-
+
}
});
});
@@ -469,7 +469,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
// add the selected culture to a cookie so the user will log back into the same culture later on (cookie lifetime = one year)
var expireDate = new Date();
expireDate.setDate(expireDate.getDate() + 365);
- $cookies.put("UMB_MCULTURE", language.culture, {path: "/", expires: expireDate});
+ $cookies.put("UMB_MCULTURE", language.culture, { path: "/", expires: expireDate });
// close the language selector
$scope.page.languageSelectorIsOpen = false;
@@ -495,9 +495,10 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
//execute them sequentially
// set selected language to active
- angular.forEach($scope.languages, function(language){
+ Utilities.forEach($scope.languages, language => {
language.active = false;
});
+
language.active = true;
angularHelper.executeSequentialPromises(promises);
@@ -538,7 +539,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
closeTree();
};
- $scope.onOutsideClick = function() {
+ $scope.onOutsideClick = function () {
closeTree();
};
diff --git a/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js b/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js
index dc40338d01..5ff8dd3633 100644
--- a/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/preview/preview.controller.js
@@ -6,8 +6,8 @@
var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.services'])
.controller("previewController", function ($scope, $window, $location) {
-
- $scope.currentCulture = {iso:'', title:'...', icon:'icon-loading'}
+
+ $scope.currentCulture = { iso: '', title: '...', icon: 'icon-loading' }
var cultures = [];
$scope.tabbingActive = false;
@@ -21,7 +21,7 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
window.addEventListener('mousedown', disableTabbingActive);
}
}
-
+
function disableTabbingActive(evt) {
$scope.tabbingActive = false;
$scope.$digest();
@@ -113,10 +113,10 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
$scope.sizeOpen = false;
$scope.cultureOpen = false;
- $scope.toggleSizeOpen = function() {
+ $scope.toggleSizeOpen = function () {
$scope.sizeOpen = toggleMenu($scope.sizeOpen);
}
- $scope.toggleCultureOpen = function() {
+ $scope.toggleCultureOpen = function () {
$scope.cultureOpen = toggleMenu($scope.cultureOpen);
}
@@ -132,8 +132,8 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
$scope.sizeOpen = false;
$scope.cultureOpen = false;
}
-
- $scope.windowClickHandler = function() {
+
+ $scope.windowClickHandler = function () {
closeOthers();
}
function windowBlurHandler() {
@@ -141,16 +141,16 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
$scope.$digest();
}
- var win = angular.element($window);
+ var win = $($window);
win.on("blur", windowBlurHandler);
-
+
$scope.$on("$destroy", function () {
- win.off("blur", handleBlwindowBlurHandlerur );
+ win.off("blur", handleBlwindowBlurHandlerur);
});
-
- function setPageUrl(){
+
+ function setPageUrl() {
$scope.pageId = $location.search().id || getParameterByName("id");
var culture = $location.search().culture || getParameterByName("culture");
@@ -204,27 +204,27 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
/* Change culture */
/*****************************************************************************/
$scope.changeCulture = function (iso) {
- if($location.search().culture !== iso) {
+ if ($location.search().culture !== iso) {
$scope.frameLoaded = false;
$scope.currentCultureIso = iso;
$location.search("culture", iso);
setPageUrl();
}
};
- $scope.registerCulture = function(iso, title, isDefault) {
- var cultureObject = {iso: iso, title: title, isDefault: isDefault};
+ $scope.registerCulture = function (iso, title, isDefault) {
+ var cultureObject = { iso: iso, title: title, isDefault: isDefault };
cultures.push(cultureObject);
}
- $scope.$watch("currentCultureIso", function(oldIso, newIso) {
+ $scope.$watch("currentCultureIso", function (oldIso, newIso) {
// if no culture is selected, we will pick the default one:
if ($scope.currentCultureIso === null) {
- $scope.currentCulture = cultures.find(function(culture) {
+ $scope.currentCulture = cultures.find(function (culture) {
return culture.isDefault === true;
})
return;
}
- $scope.currentCulture = cultures.find(function(culture) {
+ $scope.currentCulture = cultures.find(function (culture) {
return culture.iso === $scope.currentCultureIso;
})
});
@@ -252,7 +252,7 @@ var app = angular.module("umbraco.preview", ['umbraco.resources', 'umbraco.servi
});
}
- function hideUmbracoPreviewBadge (iframe) {
+ function hideUmbracoPreviewBadge(iframe) {
if (iframe && iframe.contentDocument && iframe.contentDocument.getElementById("umbracoPreviewBadge")) {
iframe.contentDocument.getElementById("umbracoPreviewBadge").style.display = "none";
}
diff --git a/src/Umbraco.Web.UI.Client/src/utilities.js b/src/Umbraco.Web.UI.Client/src/utilities.js
index bd12506358..9121ba0e25 100644
--- a/src/Umbraco.Web.UI.Client/src/utilities.js
+++ b/src/Umbraco.Web.UI.Client/src/utilities.js
@@ -66,6 +66,54 @@
*/
const isObject = val => val !== null && typeof val === 'object';
+ const isWindow = obj => obj && obj.window === obj;
+
+ const isScope = obj => obj && obj.$evalAsync && obj.$watch;
+
+ const toJsonReplacer = (key, value) => {
+ var val = value;
+ if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
+ val = undefined;
+ } else if (isWindow(value)) {
+ val = '$WINDOW';
+ } else if (value && window.document === value) {
+ val = '$DOCUMENT';
+ } else if (isScope(value)) {
+ val = '$SCOPE';
+ }
+ return val;
+ }
+ /**
+ * Equivalent to angular.toJson
+ */
+ const toJson = (obj, pretty) => {
+ if (isUndefined(obj)) return undefined;
+ if (!isNumber(pretty)) {
+ pretty = pretty ? 2 : null;
+ }
+ return JSON.stringify(obj, toJsonReplacer, pretty);
+ }
+
+ /**
+ * Equivalent to angular.fromJson
+ */
+ const fromJson = (val) => {
+ if (!isString(val)) {
+ return val;
+ }
+ return JSON.parse(val);
+ }
+
+ /**
+ * Not equivalent to angular.forEach. But like the angularJS method this does not fail on null or undefined.
+ */
+ const forEach = (obj, iterator) => {
+ if (obj) {
+ return obj.forEach(iterator);
+ }
+ return obj;
+ }
+
let _utilities = {
noop: noop,
copy: copy,
@@ -77,10 +125,13 @@
isDefined: isDefined,
isString: isString,
isNumber: isNumber,
- isObject: isObject
+ isObject: isObject,
+ fromJson: fromJson,
+ toJson: toJson,
+ forEach: forEach
};
if (typeof (window.Utilities) === 'undefined') {
window.Utilities = _utilities;
}
-})(window);
\ No newline at end of file
+})(window);
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js
index 7cfa02f95a..aa0cd54dff 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js
@@ -17,7 +17,7 @@
/* make a copy of the init model so it is possible to roll
back the changes on cancel */
- oldModel = angular.copy($scope.model);
+ oldModel = Utilities.copy($scope.model);
if (!$scope.model.title) {
$scope.model.title = "Compositions";
@@ -39,7 +39,7 @@
});
}
-
+
function isSelected(alias) {
if ($scope.model.contentType.compositeContentTypes.indexOf(alias) !== -1) {
@@ -68,7 +68,7 @@
or the confirm checkbox has been checked */
if (compositionRemoved) {
vm.allowSubmit = false;
- localizationService.localize("general_remove").then(function(value) {
+ localizationService.localize("general_remove").then(function (value) {
const dialog = {
view: "views/common/infiniteeditors/compositions/overlays/confirmremove.html",
title: value,
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypeconfigurationpicker/datatypeconfigurationpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypeconfigurationpicker/datatypeconfigurationpicker.controller.js
new file mode 100644
index 0000000000..9ee80488af
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypeconfigurationpicker/datatypeconfigurationpicker.controller.js
@@ -0,0 +1,106 @@
+/**
+ * @ngdoc controller
+ * @name Umbraco.Editors.DataTypeConfigurationPickerController
+ * @function
+ *
+ * @description
+ * The controller for the content type editor data type configuration picker dialog
+ */
+
+(function() {
+ "use strict";
+
+ function DataTypeConfigurationPicker($scope, $filter, dataTypeResource, dataTypeHelper, contentTypeResource, localizationService, editorService) {
+
+ var vm = this;
+
+ vm.configs = [];
+
+ vm.loading = true;
+
+ vm.newDataType = newDataType;
+ vm.pickDataType = pickDataType;
+ vm.close = close;
+
+ function activate() {
+ setTitle();
+ load();
+ }
+
+ function setTitle() {
+ if (!$scope.model.title) {
+ localizationService.localize("defaultdialogs_selectEditorConfiguration")
+ .then(function(data){
+ $scope.model.title = data;
+ });
+ }
+ }
+
+ function load() {
+
+ dataTypeResource.getGroupedDataTypes().then(function(configs) {
+
+ var filteredConfigs = [];
+
+ _.each(configs, function(configGroup) {
+ for(var i = 0; i
+
+
+
+
+
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.controller.js
index 167e74c25d..d622ccea52 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.controller.js
@@ -13,30 +13,23 @@
function DataTypePicker($scope, $filter, dataTypeResource, contentTypeResource, localizationService, editorService) {
var vm = this;
-
+
+ vm.showDataTypes = true;
+ vm.dataTypes = [];
+ vm.loading = true;
+ vm.loadingConfigs = false;
vm.searchTerm = "";
- vm.showTabs = false;
- vm.tabsLoaded = 0;
- vm.typesAndEditors = [];
- vm.userConfigured = [];
- vm.loading = false;
- vm.tabs = [];
- vm.labels = {};
-
- vm.onTabChange = onTabChange;
- vm.filterItems = filterItems;
- vm.showDetailsOverlay = showDetailsOverlay;
- vm.hideDetailsOverlay = hideDetailsOverlay;
- vm.pickEditor = pickEditor;
+ vm.searchResult = null;
+
+ vm.viewOptionsForEditor = viewOptionsForEditor;
vm.pickDataType = pickDataType;
+ vm.pickEditor = pickEditor;
vm.close = close;
+ vm.searchTermChanged = searchTermChanged;
function activate() {
setTitle();
- loadTabs();
- getGroupedDataTypes();
- getGroupedPropertyEditors();
-
+ loadTypes();
}
function setTitle() {
@@ -44,128 +37,104 @@
localizationService.localize("defaultdialogs_selectEditor")
.then(function(data){
$scope.model.title = data;
- });
+ }
+ );
}
}
-
- function loadTabs() {
-
- var labels = ["contentTypeEditor_availableEditors", "contentTypeEditor_reuse"];
-
- localizationService.localizeMany(labels)
- .then(function(data){
- vm.labels.availableDataTypes = data[0];
- vm.labels.reuse = data[1];
-
- vm.tabs = [{
- active: true,
- id: 1,
- label: vm.labels.availableDataTypes,
- alias: "Default",
- typesAndEditors: []
- }, {
- active: false,
- id: 2,
- label: vm.labels.reuse,
- alias: "Reuse",
- userConfigured: []
- }];
-
- });
- }
-
- function getGroupedPropertyEditors() {
-
- vm.loading = true;
-
- dataTypeResource.getGroupedPropertyEditors().then(function(data) {
- vm.tabs[0].typesAndEditors = data;
- vm.typesAndEditors = data;
- vm.tabsLoaded = vm.tabsLoaded + 1;
- checkIfTabContentIsLoaded();
- });
-
- }
-
- function getGroupedDataTypes() {
-
- vm.loading = true;
-
- dataTypeResource.getGroupedDataTypes().then(function(data) {
- vm.tabs[1].userConfigured = data;
- vm.userConfigured = data;
- vm.tabsLoaded = vm.tabsLoaded + 1;
- checkIfTabContentIsLoaded();
- });
-
- }
-
- function checkIfTabContentIsLoaded() {
- if (vm.tabsLoaded === 2) {
+
+ function loadTypes() {
+
+ dataTypeResource.getGroupedPropertyEditors().then(function(dataTypes) {
+ vm.dataTypes = dataTypes;
vm.loading = false;
- vm.showTabs = true;
- }
- }
-
- function onTabChange(selectedTab) {
- vm.tabs.forEach(function(tab) {
- tab.active = false;
});
- selectedTab.active = true;
+
+ }
+
+ function loadConfigurations() {
+
+ vm.loading = true;
+ vm.loadingConfigs = true;
+
+ dataTypeResource.getGroupedDataTypes().then(function(configs) {
+ vm.configs = configs;
+ vm.loading = false;
+ performeSearch();
+ });
+
}
- function filterItems() {
- // clear item details
- $scope.model.itemDetails = null;
-
- if (vm.searchTerm) {
- vm.showTabs = false;
-
- var regex = new RegExp(vm.searchTerm, "i");
-
- var userConfigured = filterCollection(vm.userConfigured, regex),
- typesAndEditors = filterCollection(vm.typesAndEditors, regex);
-
- var totalResults = _.reduce(_.pluck(_.union(userConfigured, typesAndEditors), 'count'), (m, n) => m + n, 0);
-
- vm.filterResult = {
- userConfigured: userConfigured,
- typesAndEditors: typesAndEditors,
- totalResults: totalResults
- };
-
+
+ function searchTermChanged() {
+
+ vm.showDataTypes = (vm.searchTerm === "");
+
+ if(vm.loadingConfigs !== true) {
+ loadConfigurations()
} else {
- vm.filterResult = null;
- vm.showTabs = true;
+ performeSearch();
}
+
}
-
+
+ function performeSearch() {
+
+ if (vm.searchTerm) {
+ if (vm.configs) {
+
+ var regex = new RegExp(vm.searchTerm, "i");
+ vm.searchResult = {
+ configs: filterCollection(vm.configs, regex),
+ dataTypes: filterCollection(vm.dataTypes, regex)
+ };
+ }
+ } else {
+ vm.searchResult = null;
+ }
+
+ }
+
function filterCollection(collection, regex) {
return _.map(_.keys(collection), function (key) {
-
- var filteredDataTypes = $filter('filter')(collection[key], function (dataType) {
- return regex.test(dataType.name) || regex.test(dataType.alias);
- });
-
return {
group: key,
- count: filteredDataTypes.length,
- dataTypes: filteredDataTypes
+ entries: $filter('filter')(collection[key], function (dataType) {
+ return regex.test(dataType.name) || regex.test(dataType.alias);
+ })
}
});
}
- function showDetailsOverlay(property) {
+
+ function viewOptionsForEditor(editor) {
+
+ var dataTypeConfigurationPicker = {
+ editor: editor,
+ property: $scope.model.property,
+ contentTypeName: $scope.model.contentTypeName,
+ view: "views/common/infiniteeditors/datatypeconfigurationpicker/datatypeconfigurationpicker.html",
+ size: "small",
+ submit: function(dataType, propertyType, isNew) {
+ submit(dataType, propertyType, isNew);
+ editorService.close();
+ },
+ close: function() {
+ editorService.close();
+ }
+ };
- var propertyDetails = {};
- propertyDetails.icon = property.icon;
- propertyDetails.title = property.name;
+ editorService.open(dataTypeConfigurationPicker);
- $scope.model.itemDetails = propertyDetails;
}
- function hideDetailsOverlay() {
- $scope.model.itemDetails = null;
+ function pickDataType(selectedDataType) {
+ selectedDataType.loading = true;
+ dataTypeResource.getById(selectedDataType.id).then(function(dataType) {
+ contentTypeResource.getPropertyTypeScaffold(dataType.id).then(function(propertyType) {
+ selectedDataType.loading = false;
+ submit(dataType, propertyType, false);
+ });
+ });
}
function pickEditor(propertyEditor) {
@@ -188,16 +157,7 @@
};
editorService.open(dataTypeSettings);
- }
- function pickDataType(selectedDataType) {
- selectedDataType.loading = true;
- dataTypeResource.getById(selectedDataType.id).then(function(dataType) {
- contentTypeResource.getPropertyTypeScaffold(dataType.id).then(function(propertyType) {
- selectedDataType.loading = false;
- submit(dataType, propertyType, false);
- });
- });
}
function submit(dataType, propertyType, isNew) {
@@ -213,9 +173,9 @@
$scope.model.submit($scope.model);
}
-
+
function close() {
- if ($scope.model.close) {
+ if($scope.model.close) {
$scope.model.close();
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.html
index 534fdc5648..768f8a8c24 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.html
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.html
@@ -15,127 +15,78 @@