From a0eba5a9d82f565e8f087853898da11b80c1e65d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 23 Oct 2018 15:02:56 +0200 Subject: [PATCH 01/34] wip testing ideas --- .../content/umbtabbedcontent.directive.js | 8 ++++++++ .../property/umbpropertyeditor.directive.js | 2 +- .../content/umb-tabbed-content.html | 19 ++++++++++++++++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js index 015255c577..e00b333a2f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js @@ -13,6 +13,14 @@ //expose the property/methods for other directives to use this.content = $scope.content; + $scope.activeVariant = _.find(this.content.variants, variant => { + return variant.active; + }); + + $scope.unlockInvariantValue = function(property) { + property.unlockInvariantValue = !property.unlockInvariantValue; + }; + $scope.$watch("tabbedContentForm.$dirty", function (newValue, oldValue) { if (newValue === true) { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbpropertyeditor.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbpropertyeditor.directive.js index 0aa2dc02c3..32cbbb31ec 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbpropertyeditor.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbpropertyeditor.directive.js @@ -12,7 +12,7 @@ function umbPropEditor(umbPropEditorHelper) { scope: { model: "=", isPreValue: "@", - preview: "@" + preview: "<" }, require: "^^form", diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html index b125457ab0..68d5d3d41c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html @@ -9,7 +9,24 @@
- + +
+ +
+
Unlock to change on all languages
+
Changes to {{property.label}} will be copied to all languages
+
+ +
+ Changes to {{property.label}} will be copied to all languages +
+
+ + + +
From 60b575825d8a464a636e75155945457b5000cd1a Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 23 Oct 2018 14:22:17 +0100 Subject: [PATCH 02/34] Adds new WIP attribute only based directive disable-tabindex - which sets all child input elements to use a tabindex of -1 --- .../util/disabletabindex.directive.js | 28 +++++++++++++++++++ .../views/components/umb-groups-builder.html | 13 +++++---- 2 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/util/disabletabindex.directive.js 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 new file mode 100644 index 0000000000..7f9a0fd2b3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/util/disabletabindex.directive.js @@ -0,0 +1,28 @@ +angular.module("umbraco.directives") + .directive('disableTabindex', function ($window, $timeout, windowResizeListener) { + + return { + restrict: 'A', //Can only be used as an attribute + link: function (scope, element, attrs) { + + //When the current element DOM subtree is modified + element.on('DOMSubtreeModified', function(e){ + //Check if any child items in e.target contain an input + var jqLiteEl = angular.element(e.target); + var childInputs = jqLiteEl.find('input'); + + console.log('jQLite childInputs', childInputs); + + //For each item in childInputs - override or set HTML attribute tabindex="-1" + angular.forEach(childInputs, function(element){ + console.log('item in loop', element); + + //TODO: Note we updating way too many times from the DOMSubtreeModified event - is this expensive? + angular.element(element).attr('tabindex', '-1'); + }); + + }); + + } + }; +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html index 2a5bc4a572..8732da91e7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html @@ -157,7 +157,7 @@
{{propertyTypeForm.groupName.errorMsg}}
- +
@@ -229,11 +229,12 @@
- - + + From 515f183b28f3e935250f879ca131290ee909d276 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 23 Oct 2018 16:00:53 +0200 Subject: [PATCH 03/34] make default language bold in selectors --- src/Umbraco.Web.UI.Client/src/less/components/editor.less | 1 - .../src/views/components/application/umb-navigation.html | 2 +- .../src/views/components/editor/umb-editor-content-header.html | 2 +- src/Umbraco.Web.UI.Client/src/views/languages/overview.html | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) 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 f045b0adca..d699193c24 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/editor.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/editor.less @@ -201,7 +201,6 @@ a.umb-variant-switcher__toggle { .umb-variant-switcher__name { display: block; - font-weight: bold; } .umb-variant-switcher__state { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html index 570ea3990b..ddb0396f34 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-navigation.html @@ -11,7 +11,7 @@   diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html index 149fccd00a..999176f608 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html @@ -41,7 +41,7 @@ - {{variant.language.name}} + {{variant.language.name}}
Open in split view
diff --git a/src/Umbraco.Web.UI.Client/src/views/languages/overview.html b/src/Umbraco.Web.UI.Client/src/views/languages/overview.html index dfec56fbc0..c55ce83417 100644 --- a/src/Umbraco.Web.UI.Client/src/views/languages/overview.html +++ b/src/Umbraco.Web.UI.Client/src/views/languages/overview.html @@ -41,7 +41,7 @@ - {{ language.name }} + {{ language.name }} {{ language.culture }} From a8ac9cf8f28f99f0ebf76e5676b5e1697876e06e Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 23 Oct 2018 15:13:35 +0100 Subject: [PATCH 04/34] MDN JS Docs suggested to use MutationObsorver as oppsoed to deprecated DOMSubtreeModified event --- .../util/disabletabindex.directive.js | 54 ++++++++++++++----- 1 file changed, 42 insertions(+), 12 deletions(-) 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 7f9a0fd2b3..64edcf5955 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 @@ -5,22 +5,52 @@ angular.module("umbraco.directives") restrict: 'A', //Can only be used as an attribute link: function (scope, element, attrs) { - //When the current element DOM subtree is modified - element.on('DOMSubtreeModified', function(e){ - //Check if any child items in e.target contain an input - var jqLiteEl = angular.element(e.target); - var childInputs = jqLiteEl.find('input'); + //Use DOM Mutation Observer + //Select the node that will be observed for mutations (native DOM element not jQLite version) + var targetNode = element[0]; - console.log('jQLite childInputs', childInputs); + // Options for the observer (which mutations to observe) + var config = { attributes: false, childList: true, subtree: false }; - //For each item in childInputs - override or set HTML attribute tabindex="-1" - angular.forEach(childInputs, function(element){ - console.log('item in loop', element); + // Callback function to execute when mutations are observed + var callback = function(mutationsList, observer) { + for(var mutation of mutationsList) { - //TODO: Note we updating way too many times from the DOMSubtreeModified event - is this expensive? - angular.element(element).attr('tabindex', '-1'); - }); + console.log('mutation', mutation); + //DOM items have been added or removed + if (mutation.type == 'childList') { + + //Check if any child items in mutation.target contain an input + var jqLiteEl = angular.element(mutation.target); + var childInputs = jqLiteEl.find('input'); + + //For each item in childInputs - override or set HTML attribute tabindex="-1" + angular.forEach(childInputs, function(element){ + console.log('item in loop', element); + + //TODO: Note we updating way too many times from the DOMSubtreeModified event - is this expensive? + angular.element(element).attr('tabindex', '-1'); + }); + } + } + }; + + // Create an observer instance linked to the callback function + var observer = new MutationObserver(callback); + + // Start observing the target node for configured mutations + //GO GO GO + observer.observe(targetNode, config); + + + //TODO: Unsure if we need to do this - to ensure the browser not trying to notify us still + //When we browse away from the page + element.on('$destroy', function(e){ + console.log('element with disable-tabindex attribute is destoryed'); + + //Remove/stop the observer + observer.disconnect(); }); } From b20acebe6a4e48f5d7c96b2c833d28442d47aa2e Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 23 Oct 2018 15:23:36 +0100 Subject: [PATCH 05/34] Cleanup unused DI stuff in this directive --- .../src/common/directives/util/disabletabindex.directive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 64edcf5955..624404c641 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,5 +1,5 @@ angular.module("umbraco.directives") - .directive('disableTabindex', function ($window, $timeout, windowResizeListener) { + .directive('disableTabindex', function () { return { restrict: 'A', //Can only be used as an attribute From 79e3a35869fcc8bb591b9dd4b148e5a8c1d9e98d Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 23 Oct 2018 16:03:49 +0100 Subject: [PATCH 06/34] WIP - Ensures the default language variant is always first then the rest of the variants are organised by A-Z --- .../Mapping/ContentItemDisplayVariationResolver.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Umbraco.Web/Models/Mapping/ContentItemDisplayVariationResolver.cs b/src/Umbraco.Web/Models/Mapping/ContentItemDisplayVariationResolver.cs index a627eab184..562797e3e3 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentItemDisplayVariationResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentItemDisplayVariationResolver.cs @@ -52,6 +52,18 @@ namespace Umbraco.Web.Models.Mapping variant.Name = source.GetCultureName(x.IsoCode); } + //Put the default language first in the list & then sort rest by a-z + var defaultLang = variants.SingleOrDefault(x => x.Language.IsDefault); + + //Remove the default lang from the list for now + variants.Remove(defaultLang); + + //Sort the remaining languages a-z + variants.OrderBy(x => x.Language.Name); + + //Insert the default lang as the first item + variants.Insert(0, defaultLang); + return variants; } return result; From b95a994f94339a22701867565f8855d9fae1f262 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Oct 2018 09:12:09 +0200 Subject: [PATCH 07/34] set opacity and disabled cursor when property is locked --- src/Umbraco.Web.UI.Client/src/less/belle.less | 1 + .../src/less/utilities/theme/_opacity.less | 19 +++++++++++++++++++ .../content/umb-tabbed-content.html | 10 ++++++---- 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/less/utilities/theme/_opacity.less diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index ac8279e3ab..f5a05c20ee 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -168,6 +168,7 @@ // Utilities @import "utilities/layout/_display.less"; +@import "utilities/theme/_opacity.less"; @import "utilities/typography/_text-decoration.less"; @import "utilities/typography/_white-space.less"; @import "utilities/_flexbox.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/utilities/theme/_opacity.less b/src/Umbraco.Web.UI.Client/src/less/utilities/theme/_opacity.less new file mode 100644 index 0000000000..4550827cdc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/utilities/theme/_opacity.less @@ -0,0 +1,19 @@ +/* + + Opacity + +*/ + +.o-100 { opacity: 1; } +.o-90 { opacity: 0.9; } +.o-80 { opacity: 0.8; } +.o-70 { opacity: 0.7; } +.o-60 { opacity: 0.6; } +.o-50 { opacity: 0.5; } +.o-40 { opacity: 0.4; } +.o-30 { opacity: 0.3; } +.o-20 { opacity: 0.2; } +.o-10 { opacity: 0.1; } +.o-05 { opacity: 0.05; } +.o-025 { opacity: 0.025; } +.o-0 { opacity: 0; } \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html index 68d5d3d41c..9ab8c509fd 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html @@ -22,10 +22,12 @@ - - +
+ + +
From c94775608aaaec61955e614c07af77e4c277d71e Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 24 Oct 2018 09:18:26 +0100 Subject: [PATCH 08/34] When returning a collection of languages - such as through the GetAllLanguages API Controller call the model mapping ensures that rather than order by name we, also put the default lang first then order a-z --- .../Models/Mapping/LanguageMapperProfile.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs index b305ee2824..6dd6135329 100644 --- a/src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs @@ -28,7 +28,21 @@ namespace Umbraco.Web.Models.Mapping { public IEnumerable Convert(IEnumerable source, IEnumerable destination, ResolutionContext context) { - return source.Select(x => context.Mapper.Map(x, null, context)).OrderBy(x => x.Name); + var langs = source.Select(x => context.Mapper.Map(x, null, context)).ToList(); + + //Put the default language first in the list & then sort rest by a-z + var defaultLang = langs.SingleOrDefault(x => x.IsDefault); + + //Remove the default lang from the list for now + langs.Remove(defaultLang); + + //Sort the remaining languages a-z + langs.OrderBy(x => x.Name); + + //Insert the default lang as the first item + langs.Insert(0, defaultLang); + + return langs; } } } From 30c312c4b09f19c23a34f73dd7467d3ab2b8f87c Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 24 Oct 2018 10:20:10 +0100 Subject: [PATCH 09/34] CSS & DOM element for overlay to prevent double click through to undelying input element --- .../src/less/components/umb-property-editor.less | 15 +++++++++++++++ .../components/property/umb-property-editor.html | 1 + 2 files changed, 16 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less index cbea6987e7..5c681d78a8 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less @@ -1,3 +1,18 @@ .umb-property-editor.-not-clickable { pointer-events: none; } + +.umb-property-editor { + position:relative; +} + +.umb-property-editor .overlay { + background: rgba(255,0,0,0.5); + display: block; + position: absolute; + top:0; + left:0; + height:100%; + width:100%; + cursor: not-allowed; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html index 13a5491184..22d5764da4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html @@ -1,3 +1,4 @@
+
From ba0d96ce2a2e8d6e235b931a66fe450e7d68e99b Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 24 Oct 2018 10:36:45 +0100 Subject: [PATCH 10/34] WIP for CSS overlay click through prevention stuff with Z-indexes --- .../src/less/components/umb-property-editor.less | 13 ++++++++++--- .../components/property/umb-property-editor.html | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less index 5c681d78a8..c1268b3410 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less @@ -1,13 +1,18 @@ .umb-property-editor.-not-clickable { - pointer-events: none; + // pointer-events: none; } .umb-property-editor { position:relative; } -.umb-property-editor .overlay { - background: rgba(255,0,0,0.5); +.umb-property-editor__view{ + z-index:1; + position:relative; +} + +.umb-property-editor__overlay { + background: rgba(255,0,255,0.5); display: block; position: absolute; top:0; @@ -15,4 +20,6 @@ height:100%; width:100%; cursor: not-allowed; + user-select: none; + z-index:2; } \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html index 22d5764da4..4b43d9634c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html @@ -1,4 +1,4 @@
-
-
+
+
From 62716fb417217ad86c1c21086c95976d165b5a52 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 24 Oct 2018 11:03:41 +0100 Subject: [PATCH 11/34] WIP disable tab index directive --- .../util/disabletabindex.directive.js | 85 ++++++++++++------- .../less/components/umb-property-editor.less | 1 - .../content/umb-tabbed-content.html | 10 +-- .../property/umb-property-editor.html | 6 +- .../views/components/umb-groups-builder.html | 3 +- 5 files changed, 64 insertions(+), 41 deletions(-) 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 624404c641..8a32f3b089 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 @@ -3,55 +3,78 @@ angular.module("umbraco.directives") return { restrict: 'A', //Can only be used as an attribute + scope: { disableTabindex: "<"}, link: function (scope, element, attrs) { - //Use DOM Mutation Observer - //Select the node that will be observed for mutations (native DOM element not jQLite version) - var targetNode = element[0]; + function enableTest(){ + //Add in observer code - // Options for the observer (which mutations to observe) - var config = { attributes: false, childList: true, subtree: false }; + //Use DOM Mutation Observer + //Select the node that will be observed for mutations (native DOM element not jQLite version) + var targetNode = element[0]; - // Callback function to execute when mutations are observed - var callback = function(mutationsList, observer) { - for(var mutation of mutationsList) { + // Options for the observer (which mutations to observe) + var config = { attributes: false, childList: true, subtree: false }; - console.log('mutation', mutation); + // Callback function to execute when mutations are observed + var callback = function(mutationsList, observer) { + for(var mutation of mutationsList) { - //DOM items have been added or removed - if (mutation.type == 'childList') { + console.log('mutation', mutation); - //Check if any child items in mutation.target contain an input - var jqLiteEl = angular.element(mutation.target); - var childInputs = jqLiteEl.find('input'); + //DOM items have been added or removed + if (mutation.type == 'childList') { - //For each item in childInputs - override or set HTML attribute tabindex="-1" - angular.forEach(childInputs, function(element){ - console.log('item in loop', element); + //Check if any child items in mutation.target contain an input + var jqLiteEl = angular.element(mutation.target); + var childInputs = jqLiteEl.find('input'); - //TODO: Note we updating way too many times from the DOMSubtreeModified event - is this expensive? - angular.element(element).attr('tabindex', '-1'); - }); + //For each item in childInputs - override or set HTML attribute tabindex="-1" + angular.forEach(childInputs, function(element){ + console.log('item in loop', element); + + //TODO: Get existing element & it's tabindex (if any set) + + + //TODO: Note we updating way too many times from the DOMSubtreeModified event - is this expensive? + angular.element(element).attr('tabindex', '-1'); + }); + } } - } + }; + + // Create an observer instance linked to the callback function + var observer = new MutationObserver(callback); + + // Start observing the target node for configured mutations + //GO GO GO + observer.observe(targetNode, config); }; - // Create an observer instance linked to the callback function - var observer = new MutationObserver(callback); - // Start observing the target node for configured mutations - //GO GO GO - observer.observe(targetNode, config); + scope.$watch('disableTabindex',(newVal, oldVal) =>{ + console.log('new val', newVal); + + if(newVal === true){ + enableTest(); + }else{ + + } + }); + + + + //TODO: Unsure if we need to do this - to ensure the browser not trying to notify us still //When we browse away from the page - element.on('$destroy', function(e){ - console.log('element with disable-tabindex attribute is destoryed'); + // element.on('$destroy', function(e){ + // console.log('element with disable-tabindex attribute is destoryed'); - //Remove/stop the observer - observer.disconnect(); - }); + // //Remove/stop the observer + // observer.disconnect(); + // }); } }; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less index c1268b3410..b019892a9f 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less @@ -12,7 +12,6 @@ } .umb-property-editor__overlay { - background: rgba(255,0,255,0.5); display: block; position: absolute; top:0; diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html index 9ab8c509fd..7663aa8997 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html @@ -9,9 +9,9 @@
- -
- + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html index 4b43d9634c..8674e4f6d3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html @@ -1,4 +1,6 @@
-
-
+
+
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html index 8732da91e7..c976899cb8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html @@ -232,8 +232,7 @@ + preview="true"> From a5b7e8b0ae1240d3d01a2b6453a216e80c6f45c4 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 24 Oct 2018 11:57:02 +0100 Subject: [PATCH 12/34] WIP put the tabindex back to what it was before --- .../util/disabletabindex.directive.js | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) 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 8a32f3b089..71d9ff0e5d 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 @@ -6,6 +6,8 @@ angular.module("umbraco.directives") scope: { disableTabindex: "<"}, link: function (scope, element, attrs) { + var tabIndexesToRollback = []; + function enableTest(){ //Add in observer code @@ -34,7 +36,17 @@ angular.module("umbraco.directives") console.log('item in loop', element); //TODO: Get existing element & it's tabindex (if any set) + //Check if the element has an existing tab index + //If so store in a collection (that when this directive is disabled/toggled) + //The tabindex is returned back to normal + var currentTabIndex = angular.element(element).attr('tabindex'); + console.log('currentTabIndex', currentTabIndex); + if(currentTabIndex){ + //A value has been set - need to track it + var itemToRevert = { dom: element, tabindex: currentTabIndex }; + tabIndexesToRollback.push(itemToRevert); + } //TODO: Note we updating way too many times from the DOMSubtreeModified event - is this expensive? angular.element(element).attr('tabindex', '-1'); @@ -58,6 +70,15 @@ angular.module("umbraco.directives") if(newVal === true){ enableTest(); }else{ + console.log('what do I need to revert', tabIndexesToRollback); + + //Stop observation? + //TODO: Will it refire the observer?! + + angular.forEach(tabIndexesToRollback, function(rollbackItem){ + console.log('item in rollback', rollbackItem); + angular.element(rollbackItem.dom).attr('tabindex', rollbackItem.tabindex); + }); } }); From 5b84702c2f10c764a3e87d8fb1c0539d11dc8b18 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 24 Oct 2018 13:37:33 +0100 Subject: [PATCH 13/34] Cleanup of disable tab directive & adds in tabbable 3rd party lib (wrapped as an AngularJS service) --- .../util/disabletabindex.directive.js | 105 ++------- .../src/common/services/tabbable.service.js | 223 ++++++++++++++++++ .../property/umb-property-editor.html | 8 +- 3 files changed, 248 insertions(+), 88 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/common/services/tabbable.service.js 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 71d9ff0e5d..35b49d0ddf 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,101 +1,40 @@ angular.module("umbraco.directives") - .directive('disableTabindex', function () { + .directive('disableTabindex', function (tabbableService) { return { restrict: 'A', //Can only be used as an attribute - scope: { disableTabindex: "<"}, link: function (scope, element, attrs) { - var tabIndexesToRollback = []; + //Select the node that will be observed for mutations (native DOM element not jQLite version) + var targetNode = element[0]; - function enableTest(){ - //Add in observer code + //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); - //Use DOM Mutation Observer - //Select the node that will be observed for mutations (native DOM element not jQLite version) - var targetNode = element[0]; + // Options for the observer (which mutations to observe) + var config = { attributes: true, childList: true, subtree: false }; - // Options for the observer (which mutations to observe) - var config = { attributes: false, childList: true, subtree: false }; + function domChange(mutationsList, observer){ + for(var mutation of mutationsList) { - // Callback function to execute when mutations are observed - var callback = function(mutationsList, observer) { - for(var mutation of mutationsList) { + //DOM items have been added or removed + if (mutation.type == 'childList') { - console.log('mutation', mutation); + //Check if any child items in mutation.target contain an input + var childInputs = tabbableService.tabbable(mutation.target); - //DOM items have been added or removed - if (mutation.type == 'childList') { - - //Check if any child items in mutation.target contain an input - var jqLiteEl = angular.element(mutation.target); - var childInputs = jqLiteEl.find('input'); - - //For each item in childInputs - override or set HTML attribute tabindex="-1" - angular.forEach(childInputs, function(element){ - console.log('item in loop', element); - - //TODO: Get existing element & it's tabindex (if any set) - //Check if the element has an existing tab index - //If so store in a collection (that when this directive is disabled/toggled) - //The tabindex is returned back to normal - var currentTabIndex = angular.element(element).attr('tabindex'); - console.log('currentTabIndex', currentTabIndex); - - if(currentTabIndex){ - //A value has been set - need to track it - var itemToRevert = { dom: element, tabindex: currentTabIndex }; - tabIndexesToRollback.push(itemToRevert); - } - - //TODO: Note we updating way too many times from the DOMSubtreeModified event - is this expensive? - angular.element(element).attr('tabindex', '-1'); - }); - } + //For each item in childInputs - override or set HTML attribute tabindex="-1" + angular.forEach(childInputs, function(element){ + angular.element(element).attr('tabindex', '-1'); + }); } - }; - - // Create an observer instance linked to the callback function - var observer = new MutationObserver(callback); - - // Start observing the target node for configured mutations - //GO GO GO - observer.observe(targetNode, config); - }; - - - scope.$watch('disableTabindex',(newVal, oldVal) =>{ - console.log('new val', newVal); - - if(newVal === true){ - enableTest(); - }else{ - console.log('what do I need to revert', tabIndexesToRollback); - - //Stop observation? - //TODO: Will it refire the observer?! - - angular.forEach(tabIndexesToRollback, function(rollbackItem){ - console.log('item in rollback', rollbackItem); - angular.element(rollbackItem.dom).attr('tabindex', rollbackItem.tabindex); - }); - } - }); + } - - - - - - //TODO: Unsure if we need to do this - to ensure the browser not trying to notify us still - //When we browse away from the page - // element.on('$destroy', function(e){ - // console.log('element with disable-tabindex attribute is destoryed'); - - // //Remove/stop the observer - // observer.disconnect(); - // }); + // 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/services/tabbable.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tabbable.service.js new file mode 100644 index 0000000000..4d8d5f68f3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/services/tabbable.service.js @@ -0,0 +1,223 @@ +//tabbable JS Lib (Wrapped in angular service) +//https://github.com/davidtheclark/tabbable + +(function() { + 'use strict'; + + function tabbableService() { + + var candidateSelectors = [ + 'input', + 'select', + 'textarea', + 'a[href]', + 'button', + '[tabindex]', + 'audio[controls]', + 'video[controls]', + '[contenteditable]:not([contenteditable="false"])' + ]; + var candidateSelector = candidateSelectors.join(','); + + var matches = typeof Element === 'undefined' + ? function () {} + : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; + + function tabbable(el, options) { + options = options || {}; + + var elementDocument = el.ownerDocument || el; + var regularTabbables = []; + var orderedTabbables = []; + + var untouchabilityChecker = new UntouchabilityChecker(elementDocument); + var candidates = el.querySelectorAll(candidateSelector); + + if (options.includeContainer) { + if (matches.call(el, candidateSelector)) { + candidates = Array.prototype.slice.apply(candidates); + candidates.unshift(el); + } + } + + var i, candidate, candidateTabindex; + for (i = 0; i < candidates.length; i++) { + candidate = candidates[i]; + + if (!isNodeMatchingSelectorTabbable(candidate, untouchabilityChecker)) continue; + + candidateTabindex = getTabindex(candidate); + if (candidateTabindex === 0) { + regularTabbables.push(candidate); + } else { + orderedTabbables.push({ + documentOrder: i, + tabIndex: candidateTabindex, + node: candidate + }); + } + } + + var tabbableNodes = orderedTabbables + .sort(sortOrderedTabbables) + .map(function(a) { return a.node }) + .concat(regularTabbables); + + return tabbableNodes; + } + + tabbable.isTabbable = isTabbable; + tabbable.isFocusable = isFocusable; + + function isNodeMatchingSelectorTabbable(node, untouchabilityChecker) { + if ( + !isNodeMatchingSelectorFocusable(node, untouchabilityChecker) + || isNonTabbableRadio(node) + || getTabindex(node) < 0 + ) { + return false; + } + return true; + } + + function isTabbable(node, untouchabilityChecker) { + if (!node) throw new Error('No node provided'); + if (matches.call(node, candidateSelector) === false) return false; + return isNodeMatchingSelectorTabbable(node, untouchabilityChecker); + } + + function isNodeMatchingSelectorFocusable(node, untouchabilityChecker) { + untouchabilityChecker = untouchabilityChecker || new UntouchabilityChecker(node.ownerDocument || node); + if ( + node.disabled + || isHiddenInput(node) + || untouchabilityChecker.isUntouchable(node) + ) { + return false; + } + return true; + } + + var focusableCandidateSelector = candidateSelectors.concat('iframe').join(','); + function isFocusable(node, untouchabilityChecker) { + if (!node) throw new Error('No node provided'); + if (matches.call(node, focusableCandidateSelector) === false) return false; + return isNodeMatchingSelectorFocusable(node, untouchabilityChecker); + } + + function getTabindex(node) { + var tabindexAttr = parseInt(node.getAttribute('tabindex'), 10); + if (!isNaN(tabindexAttr)) return tabindexAttr; + // Browsers do not return `tabIndex` correctly for contentEditable nodes; + // so if they don't have a tabindex attribute specifically set, assume it's 0. + if (isContentEditable(node)) return 0; + return node.tabIndex; + } + + function sortOrderedTabbables(a, b) { + return a.tabIndex === b.tabIndex ? a.documentOrder - b.documentOrder : a.tabIndex - b.tabIndex; + } + + // Array.prototype.find not available in IE. + function find(list, predicate) { + for (var i = 0, length = list.length; i < length; i++) { + if (predicate(list[i])) return list[i]; + } + } + + function isContentEditable(node) { + return node.contentEditable === 'true'; + } + + function isInput(node) { + return node.tagName === 'INPUT'; + } + + function isHiddenInput(node) { + return isInput(node) && node.type === 'hidden'; + } + + function isRadio(node) { + return isInput(node) && node.type === 'radio'; + } + + function isNonTabbableRadio(node) { + return isRadio(node) && !isTabbableRadio(node); + } + + function getCheckedRadio(nodes) { + for (var i = 0; i < nodes.length; i++) { + if (nodes[i].checked) { + return nodes[i]; + } + } + } + + function isTabbableRadio(node) { + if (!node.name) return true; + // This won't account for the edge case where you have radio groups with the same + // in separate forms on the same page. + var radioSet = node.ownerDocument.querySelectorAll('input[type="radio"][name="' + node.name + '"]'); + var checked = getCheckedRadio(radioSet); + return !checked || checked === node; + } + + // An element is "untouchable" if *it or one of its ancestors* has + // `visibility: hidden` or `display: none`. + function UntouchabilityChecker(elementDocument) { + this.doc = elementDocument; + // Node cache must be refreshed on every check, in case + // the content of the element has changed. The cache contains tuples + // mapping nodes to their boolean result. + this.cache = []; + } + + // getComputedStyle accurately reflects `visibility: hidden` of ancestors + // but not `display: none`, so we need to recursively check parents. + UntouchabilityChecker.prototype.hasDisplayNone = function hasDisplayNone(node, nodeComputedStyle) { + if (node === this.doc.documentElement) return false; + + // Search for a cached result. + var cached = find(this.cache, function(item) { + return item === node; + }); + if (cached) return cached[1]; + + nodeComputedStyle = nodeComputedStyle || this.doc.defaultView.getComputedStyle(node); + + var result = false; + + if (nodeComputedStyle.display === 'none') { + result = true; + } else if (node.parentNode) { + result = this.hasDisplayNone(node.parentNode); + } + + this.cache.push([node, result]); + + return result; + } + + UntouchabilityChecker.prototype.isUntouchable = function isUntouchable(node) { + if (node === this.doc.documentElement) return false; + var computedStyle = this.doc.defaultView.getComputedStyle(node); + if (this.hasDisplayNone(node, computedStyle)) return true; + return computedStyle.visibility === 'hidden'; + } + + //module.exports = tabbable; + + //////////// + + var service = { + tabbable: tabbable, + isTabbable: isTabbable, + isFocusable: isFocusable + }; + + return service; + } + + angular.module('umbraco.services').factory('tabbableService', tabbableService); + + })(); diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html index 8674e4f6d3..cb82a83168 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html @@ -1,6 +1,4 @@ -
-
-
-
-
+
+
+
From e2557697bcee66cc4075a071a5c573eae4d1d659 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 24 Oct 2018 14:08:15 +0100 Subject: [PATCH 14/34] Emit a single event if the language has been created or been saved - send through a new property in args to determine if it was new or not Then event listener updates the tree languages dropdown only when a new language has been added or deleted OR when an existing language has been saved/updated to be set as the new default language (as this now at top of list) --- .../src/controllers/navigation.controller.js | 21 ++++++++++++++----- .../src/views/languages/edit.controller.js | 12 +++++------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js index 2912755ce7..5d8f46c6db 100644 --- a/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js +++ b/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js @@ -194,7 +194,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar $rootScope.emptySection = false; } } - + })); //Listen for section state changes @@ -222,10 +222,21 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar }); })); - evts.push(eventsService.on("editors.languages.languageCreated", function (e, args) { - loadLanguages().then(function (languages) { - $scope.languages = languages; - }); + //Emitted when a language is created or an existing one saved/edited + evts.push(eventsService.on("editors.languages.languageSaved", function (e, args) { + console.log('lang event listen args', args); + 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){ + //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; + }); + } })); //This reacts to clicks passed to the body element which emits a global call to close all dialogs diff --git a/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js index 961470b03a..a11aa8bff8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js @@ -113,11 +113,9 @@ notificationsService.success(value); }); - // emit event when language is created - if($routeParams.create) { - var args = { language: lang }; - eventsService.emit("editors.languages.languageCreated", args); - } + // emit event when language is created or updated/saved + var args = { language: lang, isNew: $routeParams.create ? true : false }; + eventsService.emit("editors.languages.languageSaved", args); back(); @@ -129,7 +127,7 @@ }); } - + } function back() { @@ -145,7 +143,7 @@ } function toggleDefault() { - + // it shouldn't be possible to uncheck the default language if(vm.initIsDefault) { return; From 9a1a13ba81f601919f87e4a24dc63d6183ee77c8 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 24 Oct 2018 14:55:01 +0100 Subject: [PATCH 15/34] Fix the ordering logic - it helps if you actually assign the ordered items back to the list *facepalm* --- .../Models/Mapping/ContentItemDisplayVariationResolver.cs | 2 +- src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/Models/Mapping/ContentItemDisplayVariationResolver.cs b/src/Umbraco.Web/Models/Mapping/ContentItemDisplayVariationResolver.cs index 562797e3e3..7db491ad2e 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentItemDisplayVariationResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentItemDisplayVariationResolver.cs @@ -59,7 +59,7 @@ namespace Umbraco.Web.Models.Mapping variants.Remove(defaultLang); //Sort the remaining languages a-z - variants.OrderBy(x => x.Language.Name); + variants = variants.OrderBy(x => x.Name).ToList(); //Insert the default lang as the first item variants.Insert(0, defaultLang); diff --git a/src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs index 6dd6135329..f820d5ae54 100644 --- a/src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/LanguageMapperProfile.cs @@ -37,7 +37,7 @@ namespace Umbraco.Web.Models.Mapping langs.Remove(defaultLang); //Sort the remaining languages a-z - langs.OrderBy(x => x.Name); + langs = langs.OrderBy(x => x.Name).ToList(); //Insert the default lang as the first item langs.Insert(0, defaultLang); From 4420f101d2a8654c6201f58d0144a2e6abbe3db0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Oct 2018 20:41:58 +0200 Subject: [PATCH 16/34] add toggle to disable tabindex directive --- .../util/disabletabindex.directive.js | 49 ++++++++++--------- .../property/umb-property-editor.html | 8 +-- 2 files changed, 32 insertions(+), 25 deletions(-) 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 35b49d0ddf..800efb8c28 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 @@ -2,39 +2,44 @@ angular.module("umbraco.directives") .directive('disableTabindex', function (tabbableService) { return { - restrict: 'A', //Can only be used as an attribute + restrict: 'A', //Can only be used as an attribute, + scope: { + "disableTabindex": "<" + }, link: function (scope, element, attrs) { - //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: false }; + // Options for the observer (which mutations to observe) + var config = { attributes: true, childList: true, subtree: false }; - 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){ + angular.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/views/components/property/umb-property-editor.html b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html index cb82a83168..8674e4f6d3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html @@ -1,4 +1,6 @@ -
-
-
+
+
+
+
+
From 2137c1026b1bcfa674cb14ef3940980af144068e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Oct 2018 20:44:07 +0200 Subject: [PATCH 17/34] css cleanup --- .../less/components/umb-property-editor.less | 21 +++++++------------ .../property/umb-property-editor.html | 2 +- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less index b019892a9f..a3e094d9be 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-editor.less @@ -1,24 +1,19 @@ -.umb-property-editor.-not-clickable { - // pointer-events: none; -} - .umb-property-editor { - position:relative; + position: relative; } .umb-property-editor__view{ - z-index:1; - position:relative; + z-index: 1; + position: relative; } .umb-property-editor__overlay { display: block; position: absolute; - top:0; - left:0; - height:100%; - width:100%; - cursor: not-allowed; + top: 0; + left: 0; + height: 100%; + width: 100%; user-select: none; - z-index:2; + z-index: 2; } \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html index 8674e4f6d3..820721df9e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property-editor.html @@ -1,4 +1,4 @@ -
+
From b63b25414c4f52bed57b8929c06fdbdd06a02375 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Oct 2018 09:38:46 +0200 Subject: [PATCH 18/34] show inherted from label --- .../content/umbtabbedcontent.directive.js | 4 ++++ .../property/umbproperty.directive.js | 4 +++- .../content/umb-tabbed-content.html | 19 ++++++------------- .../components/property/umb-property.html | 4 ++++ 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js index 5176f65801..f83f441d66 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js @@ -17,6 +17,10 @@ return variant.active; }); + $scope.defaultVariant = _.find(this.content.variants, variant => { + return variant.language.isDefault; + }); + $scope.unlockInvariantValue = function(property) { property.unlockInvariantValue = !property.unlockInvariantValue; }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js index 69457a6f10..302378b8c0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js @@ -7,7 +7,9 @@ angular.module("umbraco.directives") .directive('umbProperty', function (umbPropEditorHelper, userService) { return { scope: { - property: "=" + property: "=", + showInherit: "<", + inheritsFrom: "<" }, transclude: true, restrict: 'E', diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html index 7663aa8997..cdacea7cf1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html @@ -8,19 +8,12 @@
- - - +
-
From 3b2e473a9ebc98285494538bd7fa8b85363c9245 Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Thu, 25 Oct 2018 12:38:43 +0200 Subject: [PATCH 23/34] #3433 changed layout so it looks better --- .../views/permissions/permissions.html | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html index 956b0d32ed..79e6c6c3c6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html @@ -10,11 +10,10 @@
- +
@@ -28,24 +27,29 @@
- +
+
+ +
Content Type Variation
+ Define the rules for how this content type's properties can be varied + +
+
-
Content Type Variation
- Define the rules for how this content type's properties can be varied +
- +
- +
From 3c217adc2e60fafd2103a55d62420db9eba70931 Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Thu, 25 Oct 2018 12:49:32 +0200 Subject: [PATCH 24/34] #3433 added language keys for text of culture variant permissions --- .../views/documenttypes/views/permissions/permissions.html | 6 +++--- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 3 +++ src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html index 79e6c6c3c6..cf7f960cea 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html @@ -41,15 +41,15 @@
-
Content Type Variation
- Define the rules for how this content type's properties can be varied +
+
- +
tab has no sort order Where is this composition used? This composition is currently used in the composition of the following content types: + Content Type Variation + Define the rules for how this content type's properties can be varied + Allow varying by Culture Building models diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 54d86eee5c..b38263d06a 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -1505,6 +1505,9 @@ To manage your website, simply open the Umbraco back office and start adding con tab has no sort order Where is this composition used? This composition is currently used in the composition of the following content types: + Content Type Variation + Define the rules for how this content type's properties can be varied + Allow varying by Culture Add language From 2fbe2bb3dad23ac6943889cd4ebb139c53722284 Mon Sep 17 00:00:00 2001 From: Dave Woestenborghs Date: Thu, 25 Oct 2018 12:54:17 +0200 Subject: [PATCH 25/34] #3433 added short cut for toglle allow culture variants to short cuts overview --- .../src/views/documenttypes/edit.controller.js | 8 +++++++- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 1 + src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js index 10c563a289..ec7a30f9ec 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js @@ -48,7 +48,8 @@ "shortcuts_toggleListView", "shortcuts_toggleAllowAsRoot", "shortcuts_addChildNode", - "shortcuts_addTemplate" + "shortcuts_addTemplate", + "shortcuts_toggleAllowCultureVariants" ]; onInit(); @@ -81,6 +82,7 @@ vm.labels.allowAsRoot = values[11]; vm.labels.addChildNode = values[12]; vm.labels.addTemplate = values[13]; + vm.labels.allowCultureVariants = values[14]; var buttons = [ { @@ -161,6 +163,10 @@ { "description": vm.labels.addChildNode, "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "c" }] + }, + { + "description": vm.labels.allowCultureVariants, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "v" }] } ] }, diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 9eab99a75a..b9b3d0cfed 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -680,6 +680,7 @@ Move Lines Down General Editor + Toggle allow culture variants Background colour diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index b38263d06a..0265996bbf 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -700,6 +700,7 @@ Move Lines Down General Editor + Toggle allow culture variants Background color From 4cfac8da16ce5e68334f300090563e2bc0739dbd Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 25 Oct 2018 14:54:36 +0200 Subject: [PATCH 26/34] Make it possible to add ellipsis on actions that invokes dialogs by means of OpensDialog on IAction --- src/Umbraco.Tests/Composing/ActionCollectionTests.cs | 4 ++++ .../src/less/components/tree/umb-actions.less | 9 +++++++++ .../views/components/application/umb-contextmenu.html | 4 ++-- src/Umbraco.Web/Models/Trees/MenuItem.cs | 5 +++++ src/Umbraco.Web/_Legacy/Actions/Action.cs | 2 ++ src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs | 2 ++ src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs | 3 +++ .../_Legacy/Actions/ActionCreateBlueprintFromContent.cs | 1 + src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionEmptyTranscan.cs | 2 ++ src/Umbraco.Web/_Legacy/Actions/ActionExport.cs | 2 ++ src/Umbraco.Web/_Legacy/Actions/ActionImport.cs | 2 ++ src/Umbraco.Web/_Legacy/Actions/ActionMove.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionNew.cs | 2 ++ src/Umbraco.Web/_Legacy/Actions/ActionNotify.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionNull.cs | 2 ++ src/Umbraco.Web/_Legacy/Actions/ActionPackage.cs | 2 ++ src/Umbraco.Web/_Legacy/Actions/ActionPackageCreate.cs | 2 ++ src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionRePublish.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionRefresh.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionRestore.cs | 2 ++ src/Umbraco.Web/_Legacy/Actions/ActionRights.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionSort.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs | 2 ++ src/Umbraco.Web/_Legacy/Actions/ActionUnPublish.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs | 3 +++ src/Umbraco.Web/_Legacy/Actions/ContextMenuSeperator.cs | 2 ++ src/Umbraco.Web/_Legacy/Actions/IAction.cs | 4 ++++ .../RelationTypes/TreeMenu/ActionDeleteRelationType.cs | 2 ++ .../RelationTypes/TreeMenu/ActionNewRelationType.cs | 2 ++ 36 files changed, 101 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Tests/Composing/ActionCollectionTests.cs b/src/Umbraco.Tests/Composing/ActionCollectionTests.cs index 04bd0a2e1e..46e4eee765 100644 --- a/src/Umbraco.Tests/Composing/ActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/ActionCollectionTests.cs @@ -49,6 +49,8 @@ namespace Umbraco.Tests.Composing public bool ShowInNotifier => false; public bool CanBePermissionAssigned => true; + + public bool OpensDialog => true; } public class NonSingletonAction : IAction @@ -66,6 +68,8 @@ namespace Umbraco.Tests.Composing public bool ShowInNotifier => false; public bool CanBePermissionAssigned => true; + + public bool OpensDialog => true; } #endregion diff --git a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-actions.less b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-actions.less index f52258333d..15296a6aaa 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-actions.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-actions.less @@ -51,6 +51,15 @@ text-decoration: none; } +.umb-action { + &.-opens-dialog { + .menu-label:after { + // adds an ellipsis (...) after the menu label for actions that open a dialog + content: '\2026'; + } + } +} + .umb-actions-child { .umb-action { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-contextmenu.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-contextmenu.html index 32dd57ade3..9d3fa3765d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-contextmenu.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-contextmenu.html @@ -5,7 +5,7 @@ -
\ No newline at end of file +
diff --git a/src/Umbraco.Web/Models/Trees/MenuItem.cs b/src/Umbraco.Web/Models/Trees/MenuItem.cs index 88d772b939..412cd9106d 100644 --- a/src/Umbraco.Web/Models/Trees/MenuItem.cs +++ b/src/Umbraco.Web/Models/Trees/MenuItem.cs @@ -38,6 +38,7 @@ namespace Umbraco.Web.Models.Trees SeperatorBefore = false; Icon = legacyMenu.Icon; Action = legacyMenu; + OpensDialog = legacyMenu.OpensDialog; } #endregion @@ -71,6 +72,10 @@ namespace Umbraco.Web.Models.Trees [DataMember(Name = "cssclass")] public string Icon { get; set; } + + [DataMember(Name = "opensDialog")] + public bool OpensDialog { get; set; } + #endregion #region Constants diff --git a/src/Umbraco.Web/_Legacy/Actions/Action.cs b/src/Umbraco.Web/_Legacy/Actions/Action.cs index 388a5735fd..241218ddb7 100644 --- a/src/Umbraco.Web/_Legacy/Actions/Action.cs +++ b/src/Umbraco.Web/_Legacy/Actions/Action.cs @@ -174,6 +174,7 @@ namespace Umbraco.Web._Legacy.Actions public string Alias { get; set; } public string JsFunctionName { get; set; } public string JsSource { get; set; } + public bool OpensDialog { get; set; } public PlaceboAction() { } public PlaceboAction(IAction legacyAction) @@ -185,6 +186,7 @@ namespace Umbraco.Web._Legacy.Actions Alias = legacyAction.Alias; JsFunctionName = legacyAction.JsFunctionName; JsSource = legacyAction.JsSource; + OpensDialog = legacyAction.OpensDialog; } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs b/src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs index 37de1f8e0f..c313f282ad 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs @@ -69,6 +69,9 @@ namespace Umbraco.Web._Legacy.Actions return true; } } + + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs b/src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs index 1425b27917..20dc331516 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs @@ -60,6 +60,8 @@ namespace Umbraco.Web._Legacy.Actions get { return ""; } } + public bool OpensDialog => false; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs b/src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs index 9c31c172ab..b68627c38c 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs @@ -83,6 +83,9 @@ namespace Umbraco.Web._Legacy.Actions return true; } } + + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs b/src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs index a489f1d280..5addcec99f 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs @@ -83,6 +83,9 @@ namespace Umbraco.Web._Legacy.Actions return true; } } + + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionCreateBlueprintFromContent.cs b/src/Umbraco.Web/_Legacy/Actions/ActionCreateBlueprintFromContent.cs index e00de39aea..0d028c35b4 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionCreateBlueprintFromContent.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionCreateBlueprintFromContent.cs @@ -20,6 +20,7 @@ namespace Umbraco.Web._Legacy.Actions public string Alias { get; private set; } public string JsFunctionName { get; private set; } public string JsSource { get; private set; } + public bool OpensDialog => true; public ActionCreateBlueprintFromContent() { diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs b/src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs index 09ce4d8602..53f7822d47 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs @@ -77,6 +77,9 @@ namespace Umbraco.Web._Legacy.Actions return true; } } + + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionEmptyTranscan.cs b/src/Umbraco.Web/_Legacy/Actions/ActionEmptyTranscan.cs index 7f8dd6b03c..f0da5323b9 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionEmptyTranscan.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionEmptyTranscan.cs @@ -73,6 +73,8 @@ namespace Umbraco.Web._Legacy.Actions } } + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionExport.cs b/src/Umbraco.Web/_Legacy/Actions/ActionExport.cs index df78026ea0..56b98c02f2 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionExport.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionExport.cs @@ -71,6 +71,8 @@ namespace Umbraco.Web._Legacy.Actions } } + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionImport.cs b/src/Umbraco.Web/_Legacy/Actions/ActionImport.cs index 42947cf36e..52f163ee6b 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionImport.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionImport.cs @@ -72,6 +72,8 @@ } } + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionMove.cs b/src/Umbraco.Web/_Legacy/Actions/ActionMove.cs index 80aff5736a..81d1803679 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionMove.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionMove.cs @@ -83,6 +83,9 @@ namespace Umbraco.Web._Legacy.Actions return true; } } + + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionNew.cs b/src/Umbraco.Web/_Legacy/Actions/ActionNew.cs index 72e863e38b..ef1b61efc5 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionNew.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionNew.cs @@ -70,6 +70,8 @@ namespace Umbraco.Web._Legacy.Actions } } + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionNotify.cs b/src/Umbraco.Web/_Legacy/Actions/ActionNotify.cs index ef281eecbe..fd6bc3d61a 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionNotify.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionNotify.cs @@ -76,6 +76,9 @@ namespace Umbraco.Web._Legacy.Actions return false; } } + + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionNull.cs b/src/Umbraco.Web/_Legacy/Actions/ActionNull.cs index 78c5175fb6..3344560c3f 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionNull.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionNull.cs @@ -51,6 +51,8 @@ get { return string.Empty; } } + public bool OpensDialog => false; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionPackage.cs b/src/Umbraco.Web/_Legacy/Actions/ActionPackage.cs index 832e691b48..fa17b87073 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionPackage.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionPackage.cs @@ -75,6 +75,8 @@ namespace Umbraco.Web._Legacy.Actions } } + public bool OpensDialog => false; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionPackageCreate.cs b/src/Umbraco.Web/_Legacy/Actions/ActionPackageCreate.cs index f0ccb03d8e..fdec43e810 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionPackageCreate.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionPackageCreate.cs @@ -75,6 +75,8 @@ namespace Umbraco.Web._Legacy.Actions } } + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs b/src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs index 357dfe89a4..65e9d7128e 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs @@ -83,6 +83,9 @@ namespace Umbraco.Web._Legacy.Actions return true; } } + + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs b/src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs index 6b54873c43..70c7735572 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs @@ -77,6 +77,9 @@ namespace Umbraco.Web._Legacy.Actions return true; } } + + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionRePublish.cs b/src/Umbraco.Web/_Legacy/Actions/ActionRePublish.cs index b78af779e4..312ae80825 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionRePublish.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionRePublish.cs @@ -74,6 +74,9 @@ namespace Umbraco.Web._Legacy.Actions return false; } } + + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionRefresh.cs b/src/Umbraco.Web/_Legacy/Actions/ActionRefresh.cs index 07133b4030..0abf4fcac5 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionRefresh.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionRefresh.cs @@ -81,6 +81,9 @@ namespace Umbraco.Web._Legacy.Actions return false; } } + + public bool OpensDialog => false; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionRestore.cs b/src/Umbraco.Web/_Legacy/Actions/ActionRestore.cs index da70eb1409..2a2baac070 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionRestore.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionRestore.cs @@ -27,6 +27,8 @@ public bool CanBePermissionAssigned => false; + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionRights.cs b/src/Umbraco.Web/_Legacy/Actions/ActionRights.cs index e1ee74e61c..beb3b06ddf 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionRights.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionRights.cs @@ -83,6 +83,9 @@ namespace Umbraco.Web._Legacy.Actions return true; } } + + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs b/src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs index 59044666f7..3179dc9fb5 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs @@ -82,6 +82,9 @@ namespace Umbraco.Web._Legacy.Actions return true; } } + + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionSort.cs b/src/Umbraco.Web/_Legacy/Actions/ActionSort.cs index b813dcbc8c..48f6b8d1e9 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionSort.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionSort.cs @@ -83,6 +83,9 @@ namespace Umbraco.Web._Legacy.Actions return true; } } + + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs b/src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs index ff471bc198..a04a24f4a3 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs @@ -78,6 +78,9 @@ namespace Umbraco.Web._Legacy.Actions return true; } } + + public bool OpensDialog => false; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs b/src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs index 0cc5120fd0..157fd827a6 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs @@ -77,6 +77,8 @@ namespace Umbraco.Web._Legacy.Actions } } + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionUnPublish.cs b/src/Umbraco.Web/_Legacy/Actions/ActionUnPublish.cs index 93d1da2046..cb197342f1 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionUnPublish.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionUnPublish.cs @@ -76,6 +76,9 @@ namespace Umbraco.Web._Legacy.Actions return false; } } + + public bool OpensDialog => false; + #endregion } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs b/src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs index 15458e83ad..5621d505a9 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs @@ -77,6 +77,9 @@ namespace Umbraco.Web._Legacy.Actions return true; } } + + public bool OpensDialog => false; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/ContextMenuSeperator.cs b/src/Umbraco.Web/_Legacy/Actions/ContextMenuSeperator.cs index 2c66932a04..45a1d0e1c5 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ContextMenuSeperator.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ContextMenuSeperator.cs @@ -46,6 +46,8 @@ get { return false; } } + public bool OpensDialog => false; + #endregion } } diff --git a/src/Umbraco.Web/_Legacy/Actions/IAction.cs b/src/Umbraco.Web/_Legacy/Actions/IAction.cs index 410a407517..48a752e7da 100644 --- a/src/Umbraco.Web/_Legacy/Actions/IAction.cs +++ b/src/Umbraco.Web/_Legacy/Actions/IAction.cs @@ -14,5 +14,9 @@ namespace Umbraco.Web._Legacy.Actions /// A path to a supporting JavaScript file for the IAction. A script tag will be rendered out with the reference to the JavaScript file. /// string JsSource { get; } + /// + /// Whether or not the action opens a dialog when invoked + /// + bool OpensDialog { get; } } } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionDeleteRelationType.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionDeleteRelationType.cs index cf39b17e55..5526a3d9a3 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionDeleteRelationType.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionDeleteRelationType.cs @@ -78,6 +78,8 @@ namespace umbraco.cms.presentation.developer.RelationTypes.TreeMenu get { return "javascript:actionDeleteRelationType(UmbClientMgr.mainTree().getActionNode().nodeId,UmbClientMgr.mainTree().getActionNode().nodeName);"; } } + public bool OpensDialog => true; + #endregion } } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionNewRelationType.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionNewRelationType.cs index 6018539983..cb776d5246 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionNewRelationType.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionNewRelationType.cs @@ -78,6 +78,8 @@ namespace umbraco.cms.presentation.developer.RelationTypes.TreeMenu get { return "javascript:actionNewRelationType();"; } } + public bool OpensDialog => true; + #endregion } } From bce2c43fdd26f4f901f365d278f6a424b811e78d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 26 Oct 2018 11:21:56 +0200 Subject: [PATCH 27/34] small fixes to alignment and copy --- .../views/permissions/permissions.html | 14 ++++---------- src/Umbraco.Web.UI/Umbraco/config/lang/en.xml | 6 +++--- src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml | 6 +++--- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html index cf7f960cea..ec1e528f8c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.html @@ -39,27 +39,21 @@
-
- -
- - -
-
- +
+
+
-
- +
diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 1acf30a7bd..8bc9d190fa 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -1485,9 +1485,9 @@ To manage your website, simply open the Umbraco back office and start adding con tab has no sort order Where is this composition used? This composition is currently used in the composition of the following content types: - Content Type Variation - Define the rules for how this content type's properties can be varied - Allow varying by Culture + Allow varying by culture + Allow editors to create content of this type in different languages + Allow varying by culture Building models diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index fc6ffa5ca3..a2487b2dc8 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -1507,9 +1507,9 @@ To manage your website, simply open the Umbraco back office and start adding con tab has no sort order Where is this composition used? This composition is currently used in the composition of the following content types: - Content Type Variation - Define the rules for how this content type's properties can be varied - Allow varying by Culture + Allow varying by culture + Allow editors to create content of this type in different languages + Allow varying by culture Add language From 0cb19e0dbd04786c805bd2aac010b9328f476ec9 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 26 Oct 2018 11:46:10 +0200 Subject: [PATCH 28/34] Document --- src/Umbraco.Core/Services/IContentService.cs | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index 64877e393e..7371686c7c 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -368,6 +368,11 @@ namespace Umbraco.Core.Services /// A publishing document is a document with values that are being published, i.e. /// that have been published or cleared via and /// . + /// When one needs to publish or unpublish a single culture, or all cultures, using + /// and is the way to go. But if one needs to, say, publish two cultures and unpublish a third + /// one, in one go, then one needs to invoke and + /// on the content itself - this prepares the content, but does not commit anything - and then, invoke + /// to actually commit the changes to the database. /// The document is *always* saved, even when publishing fails. /// PublishResult SavePublishing(IContent content, int userId = 0, bool raiseEvents = true); @@ -375,11 +380,30 @@ namespace Umbraco.Core.Services /// /// Saves and publishes a document branch. /// + /// + /// Unless specified, all cultures are re-published. Otherwise, one culture can be specified. To act on more + /// that one culture, see the other overload of this method. + /// The parameter determines which documents are published. When false, + /// only those documents that are already published, are republished. When true, all documents are + /// published. + /// IEnumerable SaveAndPublishBranch(IContent content, bool force, string culture = "*", int userId = 0); /// /// Saves and publishes a document branch. /// + /// + /// The parameter determines which documents are published. When false, + /// only those documents that are already published, are republished. When true, all documents are + /// published. + /// The parameter is a function which determines whether a document has + /// values to publish (else there is no need to publish it). If one wants to publish only a selection of + /// cultures, one may want to check that only properties for these cultures have changed. Otherwise, other + /// cultures may trigger an unwanted republish. + /// The parameter is a function to execute to publish cultures, on + /// each document. It can publish all, one, or a selection of cultures. It returns a boolean indicating + /// whether the cultures could be published. + /// IEnumerable SaveAndPublishBranch(IContent content, bool force, Func editing, Func publishCultures, int userId = 0); /// From 45cb56b96c1b0cbbe0adb0a4c0fccc38010761dc Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 26 Oct 2018 12:36:59 +0200 Subject: [PATCH 29/34] Fix ContentCultureInfos and collection --- src/Umbraco.Core/Models/ContentCultureInfos.cs | 10 +++++----- .../Models/ContentCultureInfosCollection.cs | 6 +++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Core/Models/ContentCultureInfos.cs b/src/Umbraco.Core/Models/ContentCultureInfos.cs index bcf1dbb1b1..f51e3a275a 100644 --- a/src/Umbraco.Core/Models/ContentCultureInfos.cs +++ b/src/Umbraco.Core/Models/ContentCultureInfos.cs @@ -28,11 +28,11 @@ namespace Umbraco.Core.Models /// Initializes a new instance of the class. /// /// Used for cloning, without change tracking. - private ContentCultureInfos(string culture, string name, DateTime date) - : this(culture) + internal ContentCultureInfos(ContentCultureInfos other) + : this(other.Culture) { - _name = name; - _date = date; + _name = other.Name; + _date = other.Date; } /// @@ -61,7 +61,7 @@ namespace Umbraco.Core.Models /// public object DeepClone() { - return new ContentCultureInfos(Culture, Name, Date); + return new ContentCultureInfos(this); } /// diff --git a/src/Umbraco.Core/Models/ContentCultureInfosCollection.cs b/src/Umbraco.Core/Models/ContentCultureInfosCollection.cs index 5238e65631..82b0ba6475 100644 --- a/src/Umbraco.Core/Models/ContentCultureInfosCollection.cs +++ b/src/Umbraco.Core/Models/ContentCultureInfosCollection.cs @@ -24,8 +24,12 @@ namespace Umbraco.Core.Models public ContentCultureInfosCollection(IEnumerable items) : base(x => x.Culture, StringComparer.InvariantCultureIgnoreCase) { + // make sure to add *copies* and not the original items, + // as items can be modified by AddOrUpdate, and therefore + // the new collection would be impacted by changes made + // to the old collection foreach (var item in items) - Add(item); + Add(new ContentCultureInfos(item)); } /// From e0365d4214618bdbbc0f8f18477cc903104ba764 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 26 Oct 2018 13:17:12 +0200 Subject: [PATCH 30/34] add ellipsis to action menu items that opens a dialog + fix action menu not opening anything --- .../src/views/components/editor/umb-editor-content-header.html | 2 +- .../src/views/components/editor/umb-editor-menu.html | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html index 149fccd00a..e0f40a1b3b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html @@ -72,7 +72,7 @@ + current-section="{{menu.currentNode.section}}">
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-menu.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-menu.html index f724f39be7..bf9c8fab8c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-menu.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-menu.html @@ -8,7 +8,7 @@
From ed4439e3d53a9a84a7582e1141e9383d5aabd7ed Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 26 Oct 2018 13:36:05 +0200 Subject: [PATCH 31/34] add ellipsis to more items --- .../insertcodesnippet/insertcodesnippet.html | 9 ++++----- .../src/views/components/umb-groups-builder.html | 3 ++- .../src/views/datatypes/create.html | 2 +- .../src/views/documenttypes/create.html | 4 ++-- .../src/views/mediatypes/create.html | 2 +- .../src/views/partialviewmacros/create.html | 4 ++-- .../src/views/partialviews/create.html | 4 ++-- src/Umbraco.Web.UI.Client/src/views/scripts/create.html | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/insertcodesnippet/insertcodesnippet.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/insertcodesnippet/insertcodesnippet.html index 58b422ceb2..2ccbf11cc1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/insertcodesnippet/insertcodesnippet.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/insertcodesnippet/insertcodesnippet.html @@ -16,24 +16,23 @@
-
+
...
-
+
...
-
+
...
-
-
+
...
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html index 2a5bc4a572..1e8c1f74e5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html @@ -13,7 +13,8 @@ label-key="contentTypeEditor_compositions" icon="icon-merge" action="openCompositionsDialog()" - size="xs"> + size="xs" + add-ellipsis="true"> - New folder + New folder... diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.html index d19b1329d2..c9f62cd870 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.html @@ -25,7 +25,7 @@ - Document Type Collection + Document Type Collection... @@ -33,7 +33,7 @@
  • - + ...
  • diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/create.html b/src/Umbraco.Web.UI.Client/src/views/mediatypes/create.html index ca85bcbf9e..795fd0ba7b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/create.html @@ -16,7 +16,7 @@
  • - + ...
  • diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.html b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.html index 36ab0e71c1..74a611b3d9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.html @@ -25,13 +25,13 @@
  • - >New partial view macro from snippet + >New partial view macro from snippet...
  • - + ...
  • diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviews/create.html b/src/Umbraco.Web.UI.Client/src/views/partialviews/create.html index 59c0b0b344..cfeb2396a7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviews/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/partialviews/create.html @@ -18,13 +18,13 @@
  • - New partial view from snippet + New partial view from snippet...
  • - + ...
  • diff --git a/src/Umbraco.Web.UI.Client/src/views/scripts/create.html b/src/Umbraco.Web.UI.Client/src/views/scripts/create.html index d4c21b4b8a..8b5e0732d2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/scripts/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/scripts/create.html @@ -13,7 +13,7 @@
  • - + ...
  • From 628895cc89c59d66de1cbea95bd59952d03f2408 Mon Sep 17 00:00:00 2001 From: Stephan Date: Fri, 26 Oct 2018 14:38:30 +0200 Subject: [PATCH 32/34] In-Progress in ContentService --- .../Services/Implement/ContentService.cs | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index 200c5af096..f14747cda3 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -1272,12 +1272,49 @@ namespace Umbraco.Core.Services.Implement bool IsEditing(IContent c, string l) => c.PublishName != c.Name || - c.PublishedCultures.Any(x => c.GetCultureName(x) != c.GetPublishName(x)) || - c.Properties.Any(x => x.Values.Where(y => culture == "*" || y.Culture == l).Any(y => !y.EditedValue.Equals(y.PublishedValue))); + c.PublishedCultures.Where(x => x.InvariantEquals(l)).Any(x => c.GetCultureName(x) != c.GetPublishName(x)) || + c.Properties.Any(x => x.Values.Where(y => culture == "*" || y.Culture.InvariantEquals(l)).Any(y => !y.EditedValue.Equals(y.PublishedValue))); return SaveAndPublishBranch(content, force, document => IsEditing(document, culture), document => document.PublishCulture(culture), userId); } + // fixme - make this public once we know it works + document + private IEnumerable SaveAndPublishBranch(IContent content, bool force, string[] cultures, int userId = 0) + { + // note: EditedValue and PublishedValue are objects here, so it is important to .Equals() + // and not to == them, else we would be comparing references, and that is a bad thing + + cultures = cultures ?? Array.Empty(); + + // determines whether the document is edited, and thus needs to be published, + // for the specified cultures (it may be edited for other cultures and that + // should not trigger a publish). + bool IsEdited(IContent c) + { + if (cultures.Length == 0) + { + // nothing = everything + return c.PublishName != c.Name || + c.PublishedCultures.Any(x => c.GetCultureName(x) != c.GetPublishName(x)) || + c.Properties.Any(x => x.Values.Any(y => !y.EditedValue.Equals(y.PublishedValue))); + } + + return c.PublishName != c.Name || + c.PublishedCultures.Where(x => cultures.Contains(x, StringComparer.InvariantCultureIgnoreCase)).Any(x => c.GetCultureName(x) != c.GetPublishName(x)) || + c.Properties.Any(x => x.Values.Where(y => cultures.Contains(y.Culture, StringComparer.InvariantCultureIgnoreCase)).Any(y => !y.EditedValue.Equals(y.PublishedValue))); + } + + // publish the specified cultures + bool PublishCultures(IContent c) + { + return cultures.Length == 0 + ? c.PublishCulture() // nothing = everything + : cultures.All(c.PublishCulture); + } + + return SaveAndPublishBranch(content, force, IsEdited, PublishCultures, userId); + } + /// public IEnumerable SaveAndPublishBranch(IContent document, bool force, Func editing, Func publishCultures, int userId = 0) From f4b970e88741fac418aec9692971cae199f30e78 Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 29 Oct 2018 11:21:30 +0100 Subject: [PATCH 33/34] Fix timing-dependent test --- src/Umbraco.Tests/Persistence/LocksTests.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Tests/Persistence/LocksTests.cs b/src/Umbraco.Tests/Persistence/LocksTests.cs index 819dbc89ed..56779ace0f 100644 --- a/src/Umbraco.Tests/Persistence/LocksTests.cs +++ b/src/Umbraco.Tests/Persistence/LocksTests.cs @@ -203,7 +203,14 @@ namespace Umbraco.Tests.Persistence Assert.IsNotNull(e1); Assert.IsInstanceOf(e1); - Assert.IsNull(e2); + // the assertion below depends on timing conditions - on a fast enough environment, + // thread1 dies (deadlock) and frees thread2, which succeeds - however on a slow + // environment (CI) both threads can end up dying due to deadlock - so, cannot test + // that e2 is null - but if it's not, can test that it's a timeout + // + //Assert.IsNull(e2); + if (e2 != null) + Assert.IsInstanceOf(e2); } private void DeadLockTestThread(int id1, int id2, EventWaitHandle myEv, WaitHandle otherEv, ref Exception exception) From 777d88ed8ff234386e8a5c69172ffb00b687592f Mon Sep 17 00:00:00 2001 From: Robert Date: Mon, 29 Oct 2018 12:38:46 +0100 Subject: [PATCH 34/34] Fixed unit test --- src/Umbraco.Tests/UI/LegacyDialogTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests/UI/LegacyDialogTests.cs b/src/Umbraco.Tests/UI/LegacyDialogTests.cs index 99391104ab..be9b0d4d7e 100644 --- a/src/Umbraco.Tests/UI/LegacyDialogTests.cs +++ b/src/Umbraco.Tests/UI/LegacyDialogTests.cs @@ -23,7 +23,7 @@ namespace Umbraco.Tests.UI } } - [TestCase(typeof(macroTasks), Constants.Applications.Packages)] + [TestCase(typeof(macroTasks), Constants.Applications.Settings)] [TestCase(typeof(CreatedPackageTasks), Constants.Applications.Packages)] public void Check_Assigned_Apps_For_Tasks(Type taskType, string app) {